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.