Metodo sicuro per archiviare oggetti PHP nel database MySQL?

3

Come faccio a salvare in modo sicuro gli oggetti PHP in un database MySQL? Se usi le funzioni serialize e unserialize, potresti finire con Iniezioni di oggetti . C'è uno standard predefinito su come gestirlo?

Si noti che SQL injection = / = object injection! Quindi DOP è una storia diversa qui!

    
posta Critical joe 20.08.2016 - 14:49
fonte

3 risposte

2

(Non) Fidato del tuo database

Dovresti essere in grado di fidarti un po 'dei dati nel tuo database, ma come difesa in profondità è decisamente meglio non fidarti di esso.

Potrebbe esserci per esempio un'iniezione SQL limitata, che consente l'inserimento di dati nel database, ma nient'altro (forse perché i tuoi diritti di database sono gestiti correttamente).

Ma ora, un utente malintenzionato ha ottenuto l'iniezione di oggetti e chissà cosa potrebbe comportare.

Integrità dei dati

Potresti utilizzare un HMAC per verificare l'integrità dei tuoi dati. In questo modo, puoi essere sicuro che ciò che è entrato nel database è la stessa cosa che ne deriva (purché un utente malintenzionato non abbia accesso alla chiave, che ad esempio può essere memorizzata nel codice sorgente).

Salva unserialize

PHP7 consente un parametro opzioni aggiuntive, in cui è possibile specificare quali classi unserialize è consentito creare.

Questo limita già la potenza dell'iniezione dell'oggetto. Un utente malintenzionato può ancora sovrascrivere i campi nell'oggetto stesso, che possono comunque eseguire se si presuppone l'accesso in scrittura al database, che potrebbe non essere dannoso, ma non possono creare oggetti arbitrari.

Convalida dell'input

Potresti anche eseguire alcune convalide sui dati prima di inviarli a unserialize, come raccogliere tutte le stringhe O:X e controllare se X è un oggetto consentito.

Ma raccomando vivamente di salvare la soluzione unserialize dall'alto.

Mitigazione: non avere classi e funzioni sfruttabili

È una buona idea controllare i dati e l'autenticazione a livello di funzione. Ad esempio, non dovresti semplicemente assumere che il campo x può essere considerato attendibile perché non è (attualmente) controllato dall'utente, e quindi ad esempio è sicuro passare al passthru.

Non memorizzare oggetti

Se non hai una buona ragione per farlo, non dovresti memorizzare oggetti nel database.

    
risposta data 20.08.2016 - 15:52
fonte
1

Se non ti fidi del tuo database, l'iniezione di oggetti è probabilmente l'ultima delle tue preoccupazioni. Il collegamento che fornisci in particolare riguarda i dati forniti dall'utente. È un caso inusuale in cui riceverai dati serializzati in PHP da un client al di fuori dello stack di applicazioni.

La soluzione è semplice e, come sempre, verificare che i dati definiti dall'utente rientrino in limiti accettabili. Mentre è possibile utilizzare un metodo magico wakeup per verificare un'iniezione dell'oggetto inaspettata (leggermente più semplice dell'implementazione del proprio unseralizer) una soluzione migliore è mantenere una firma dei dati serializzati e molto prima di non serializzare:

 define('SERIALIZE_SALT', 's3cr3t5auce');

 function signed_unserialize($serialized, $signature)
 {
     if (sha1($serialized . SERIALIZE_SALT) === $signature) {
        return unserialize($serialized));
     } else {
        whatever();
        return new stdClass();
     }
    }

Tuttavia, penso che dovrei sottolineare che l'uso di un database relazionale per memorizzare oggetti opachi (e per questo, banale ORM) risulta in applicazioni difficili da mantenere e molto difficili da scalare. Questi problemi e il tuo problema originale sono associati normalizzando il tuo database e implementando le fabbriche nella tua applicazione).

    
risposta data 20.08.2016 - 15:15
fonte
0

La serializzazione degli oggetti in PHP è un campo minato che faresti meglio a rimanere fuori. Il manuale viene fornito con un grande avvertimento rosso:

Warning! Do not pass untrusted user input to unserialize() regardless of the options value of allowed_classes. Unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this. Use a safe, standard data interchange format such as JSON (via json_decode() and json_encode()) if you need to pass serialized data to the user.

If you need to unserialize externally-stored serialized data, consider using hash_hmac() for data validation. Make sure data is not modified by anyone but you.

Dovresti sempre considerare i dati dal database come dati non attendibili. Quindi non dovresti chiamare unserialize su di esso. La soluzione HMAC sopra citata funzionerebbe se eseguita correttamente, ma è molto facile ottenere qui i dettagli sbagliati.

Quindi il mio consiglio è semplicemente di bloccare quella malvagia funzione unserialize nella tua php.ini , e andare invece con JSON.

    
risposta data 28.02.2018 - 17:08
fonte

Leggi altre domande sui tag