Ho scoperto un modulo web che accetta un email e un codice promozionale e, se il codice è valido, riceverai un regalo in-game. Purtroppo, non avevo codici promozionali, tuttavia ho trovato questo modulo per contenere le vulnerabilità di SQL injection su entrambi i campi.
Dichiarazione di non responsabilità: Dopo aver scoperto la vulnerabilità iniziale, l'ho segnalato al proprietario del server e ho chiesto il permesso di dare un'occhiata, quindi mi ha concesso il permesso e rimosso il forma vulnerabile dall'accesso pubblico.
Sono riuscito a ricostruire la logica remota (in pseudocodice):
handle(code, email) {
cursor = 'SELECT type, date FROM codes WHERE code='${code}' LIMIT 1';
if (cursor.rows != 0) {
'INSERT INTO codes
(code, type, email, date)
VALUES ('already_used', 0, '${email}', NOW())';
return 'Error: promo code has already been used';
}
if (cursor.date != NULL) {
'INSERT INTO codes
(code, type, email, date)
VALUES ('invalid', 0, '${email}', NOW())';
return 'Error: invalid promo code';
}
'UPDATE codes SET email='${email}', date=NOW() WHERE code='${code}'';
if (cursor.type == 2) {
send_mail(to=email, "<html>You have used promo ${code}, but the cake is a lie.</html>");
}
return 'HUGE SUCCESS! You will now get a cake.';
}
E lo schema della tabella codes
è apparentemente come segue:
CREATE TABLE codes (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code CHAR(16) NOT NULL,
type INT NOT NULL,
email VARCHAR(256),
date DATETIME
);
L'iniezione nel campo code
è cieca - quindi posso verificare se SQL expr
è vero ("promo già utilizzato") o falso ("promo non valido"). Sto usando ' OR (${expr}) #
vector.
Ho espanso questo canale per consentire il passaggio dei risultati delle stringhe. Per prima cosa rilevo la lunghezza del risultato tramite i controlli ' OR ((${expr}) REGEXP '^.{N,}') #
, utilizzando la ricerca binaria per trovare il N
corretto. Quindi rivelo il risultato char per char utilizzando query di intervallo come ' OR (CONVERT((${expr}) USING BINARY) REGEXP '^id[[.comma.]][f-k]') #
tramite la ricerca binaria per ogni carattere.
In questo modo ho imparato il VERSION()
(MySQL 5.1.73-cll), lo schema esatto della tabella codes
tramite information_schema
introspection, i nomi di altri database ecc. Non ho il permesso FILE
, quindi non posso usare LOAD_FILE()
.
Sfruttando l'iniezione nel campo email
, sono riuscito a registrare un nuovo codice promozionale tramite ', NOW()), ('fake-promo', 2, NULL, NULL) #
vector.
Poiché gli avvertimenti non sono stati soppressi, conosco il percorso assoluto dello script PHP che gestisce queste richieste. Sfortunatamente, poiché mi manca l'autorizzazione FILE
, non conosco il modo di ottenere la sua fonte. Dagli avvertimenti posso anche dire che lo script usa obsolete mysql_query()
e mysql_num_rows()
API.
Lo script invia email che hanno X-Source-Args
e X-Source-Dir
di intestazioni impostate (e PHP sembra funzionare sotto apache2), quindi posso concludere che le e-mail sono inviate tramite la funzione% di% di conversione in%.
Quindi, quali sono i miei ulteriori passi nell'esplorazione del sistema?
Sto suggerendo che mail()
potrebbe essere sfruttabile con una sorta di iniezione di shell tramite il destinatario falsificato mail
, tuttavia non sono sicuro da dove iniziare.
Forse anche altri vettori di attacco? Rendendo email
, UPDATE
o INSERT
possibile su tabelle arbitrarie? Rompendo il mio canale di comunicazione a un bit? Leggendo la fonte dello script PHP?