La conversione indesiderata di un numero scientifico è una vulnerabilità?

29

Ho notato in diversi test di penetrazione che PHP sta convertendo valori come 1e9 in 1000000000 mentre la lunghezza massima della stringa accettata di questo numero è 3 (nella memoria del database e come proprietà maxlength nei moduli HTML).

Tuttavia, inserendo 1e9 (3), PHP restituirà 1000000000 (10) come output. Questo è un numero maggiore di quello che l'applicazione si aspetta e può gestire correttamente. Pertanto, prenderei in considerazione una migliore convalida dell'input dell'utente per impedirlo.

In primo luogo, presumo che questo comportamento non sia pericoloso ma semplicemente indesiderabile, è legittimo presumere questo? In secondo luogo, posso considerarlo come una vulnerabilità effettiva (bassa gravità)?

Anche l'input 9e9 risulterà nel valore massimo a 32 bit 2147483647 (10) anziché 9000000000 (10). È solo questo (sistema o configurazione a 32 bit) considerato come perdita di informazioni di sistema o comunque pericoloso?

    
posta Bob Ortiz 20.06.2016 - 11:56
fonte

2 risposte

18

In senso stretto? No, di per sé non è una vulnerabilità. Ma suggerisce che c'è potenzialmente un problema che richiede ulteriori indagini.

Questo è uno dei problemi inerenti al test delle penne. Trovi qualcosa di ambiguo come questo, e non sai se è sfruttabile. Per iniziare anche a scoprire se si tratta di una vulnerabilità, è necessario capire cosa fa la limitazione di input.

Ad esempio, se il programma è stato progettato per limitare i trasferimenti bancari a meno di $ 1000 e il campo di input era l'importo, e non ci sono ulteriori controlli da nessuna parte, hai appena trovato un'enorme vulnerabilità.

D'altra parte, se il campo è solo le prime 3 cifre di un numero di telefono che crea un database di numeri di telefono per i genitori per immettere i numeri di contatto per una scuola, e la convalida è semplicemente per assicurarsi che l'utente inserisca solo il le prime 3 cifre, probabilmente non hai trovato altro che un caso in cui un genitore molto nerd può rovinare la propria voce # nel database.

    
risposta data 20.06.2016 - 16:16
fonte
26

Perché succede?

È perché PHP ha digitazione libera . Dai un'occhiata a questo esempio:

$x = "1e6";
echo strlen($x); // 3
echo $x * 1;     // 1 000 000

Sulla seconda riga, si assume che $x sia una stringa, e come tale è ovviamente lunga tre caratteri. Sulla terza riga, $x è interpretato come un numero intero, o 1 000 000 in questo caso.

È un problema?

Questo può sicuramente causare bug, e ogni bug è una potenziale vulnerabilità di sicurezza. Ma da solo, non rende vulnerabile la tua applicazione di default. Ma proviamo a immaginare uno scenario in cui potrebbe causare un problema.

Diciamo che un forum ha gruppi numerati che gli utenti possono liberamente aderire, ma i primi 10 gruppi (da 0 a 9) sono riservati agli amministratori. Il codice per joingroup.php assomiglia a questo:

$group = $_POST['group'];
if(strlen($group) > 1 || $isadmin) {
    join_group($group, $uid);
}
else {
    // Fail.
}

Potresti entrare di nascosto in un gruppo di amministratori senza essere effettivamente un amministratore pubblicando, ad es. 0.3e1 , che ha una lunghezza di stringa 5 ma valuta 3. So, è un esempio stupido. Il punto che voglio fare è che se ti affidi a strlen() (o qualsiasi altra cosa che tratti l'input come stringa) per convalidare i dati numerici, potresti essere vulnerabile.

Il solo posting 3.0 o  3 ignorerebbe anche questo controllo. Per ulteriori informazioni su come PHP converte implicitamente le stringhe in numeri, seleziona il manuale .

Come dovrei affrontare questo in PHP?

Convalida l'input dell'utente. Verifica di avere effettivamente un numero intero quando pensi di ottenere un intero:

if(!ctype_digit($group)) {
    // Fail.
}

È anche una buona idea trattare sempre qualcosa che dovrebbe essere un numero intero come numero intero e non una stringa:

$group = (int) $_POST['group']
if($group > 9 || $isadmin) {
    // ...

Le informazioni del sistema sono fuoriuscite?

Apparentemente questo può rivelare il valore intero massimo. Forse qualcuno potrebbe dedurre che stai usando PHP da questo, ma ci sono probabilmente molti altri modi per farlo già. Il valore massimo dipende dalla piattaforma, quindi potrebbe essere utilizzato per le impronte digitali. Ma in pratica i 32 bit sono probabilmente utilizzati su un sistema a 32 bit e 64 bit su un sistema a 64 bit. Quindi questa è l'unica informazione che stai perdendo.

    
risposta data 20.06.2016 - 13:26
fonte