L'iniezione SQL è un semplice vettore di attacco ancora molto comune oggi. Il motivo non è altro che l'assenza di una patch per lo stupido. Perché lo dici? Prendiamo JAVA come esempio per illustrare:
Supponiamo che esista una tabella come questa nel database:
Poi usa la tabella delle azioni JDBC:
Il codice sopra è spesso utilizzato da alcuni sviluppatori. Immagina una situazione in cui il parametro userId in ingresso è "3; Drop table utente; L'istruzione SQL eseguita è la seguente:
Dopo che il database è stato compilato ed eseguito, la tabella utente viene eliminata. Voilà, un semplice attacco di SQL injection prende effetto! Questo perché il codice sopra non è conforme alle specifiche di programmazione.
Quando programmiamo secondo la specifica, l'iniezione SQL è inesistente. È anche cosìIl primo modo per evitare l'iniezione SQL: istruzioni precompilate, il codice è il seguente:
Perché l'iniezione SQL non esiste nel codice sopra descritto? Poiché viene utilizzata la dichiarazione precompilata, la dichiarazione precompilata imposterà "seleziona nome dall'utente dove id= ?" L'istruzione viene compilata in anticipo in modo che debba essere sostituita solo con i parametri in ingresso quando viene eseguita? I segnaposto vanno bene. Nel primo caso non conforme, il programma scriverà un'istruzione SQL e poi la compilerà con il contenuto passato dall'utente, che è proprio il problema.
Oltre all'uso di istruzioni precompilate, esiste una seconda opzioneModi per evitare attacchi tramite iniezione SQL: stored procedure。 Una stored procedure è un insieme di istruzioni SQL che svolgono una funzione specifica, compilate e memorizzate in un database, e l'utente può eseguirla chiamando una stored procedure e fornendo un parametro (se la stored procedure ha parametri), il che può anche evitare attacchi SQL injection
La procedura memorizzata corrispondente nel codice sopra è la seguente:
Naturalmente, gli utenti possono anche effettuare il controllo dei caratteri nel frontend, che è anche un modo per evitare l'iniezione SQL: ad esempio, per il parametro userId sopra, l'utente controllerà un punto e virgola e verrà visualizzato un errore. Tuttavia, la ragione più fondamentale è che esistono attacchi di iniezione SQL perché le app non utilizzano il minimo privilegio nell'accesso ai database. Sembra che tutti abbiano usato l'account root per accedere al database.
Quindi, come fa MyBatis a evitare gli attacchi tramite SQL injection? Oppure prendiamo l'utente della tabella sopra come esempio: Supponiamo che il file mapper sia:
I corrispondenti file Java sono:
Puoi vedere che il parametro di input è userId di tipo String, quando passiamo userId="34; Drop table utente; Dopodiché, la dichiarazione stampata recita:
Indipendentemente dall'userID inserito, la sua istruzione SQL è così. Ciò è dovuto al fatto che mybatis utilizza istruzioni precompilate nell'implementazione sottostante. Quando il database esegue quell'istruzione, usa direttamente l'istruzione precompilata e poi sostituisce il segnaposto con l'userID che passa? Vai a correre. Sostituire prima i segnaposto? Il processo di compilazione viene eseguito, quindi non c'è spazio per la sopravvivenza dell'iniezione SQL.
Quindi, come fa MyBatis a gestire la precompilazione SQL? In effetti, la classe PreparedStatement viene utilizzata alla base del framework. La classe PreparedStaement non solo evita l'iniezione SQL, ma risparmia anche (N-1) tempo di compilazione quando la stessa istruzione SQL viene eseguita N volte, migliorando così l'efficienza.
Se cambi l'affermazione sopra in:
Quando inseriamo userId="34; Drop table utente; Dopodiché, la dichiarazione stampata recita:
Al momento, mybatis non utilizza istruzioni precompilate, prima cucisce stringhe e poi compiole, che è esattamente come entra in gioco l'iniezione SQL.
Pertanto, quando scrivi istruzioni di mappatura mybatis, prova a usare il formato "#{xxx}". Se devi usare parametri come "${xxx}", devi filtrarli manualmente per prevenire attacchi di iniezione SQL.
|