logo

Injecció SQL

SQL Injection és una fallada de seguretat a les aplicacions web on els atacants insereixen codi SQL nociu mitjançant l'entrada de l'usuari. Això els pot permetre accedir al contingut de la base de dades de canvi de dades sensibles o fins i tot prendre el control del sistema. És important saber sobre SQL Injection per mantenir les aplicacions web segures.

SQL Injection (SQLi) és una vulnerabilitat de seguretat que es produeix quan un atacant pot manipular les consultes de la base de dades d'una aplicació web inserint codi SQL maliciós als camps d'entrada de l'usuari. Aquestes consultes injectades poden manipular la base de dades subjacent per recuperar dades modificades o suprimides. En alguns casos, els atacants poden fins i tot augmentar els privilegis obtenint el control total sobre la base de dades o el servidor.



injecció sql' title=

Exemple del món real:

El 2019 es va produir la violació de dades de Capital One a causa d'una aplicació web mal configurada que va permetre a un atacant explotar una vulnerabilitat d'injecció SQL. Això va provocar la filtració de dades personals de més de 100 milions de clients, incloent noms, adreces i puntuacions de crèdit.

Nivell de seguretat d'injecció SQL

DVWA ofereix quatre nivells de seguretat per a SQL Injection per ajudar els estudiants a veure com les diferents proteccions afecten els atacs:



1. Baixa seguretat

L'aplicació pren la vostra entrada i la posa directament a la consulta SQL sense cap filtre.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Entrant ': Trenca la consulta i fa que la base de dades llanci un error que revela que és vulnerable.
  • Entrant 1' OR '1'='1: Enganya la consulta perquè sempre sigui certa perquè es tornin tots els usuaris.
  • Entrant 1' UNION SELECT user password FROM users--: S'uneix a una altra consulta per obtenir dades ocultes com ara noms d'usuari i contrasenyes.

2. Seguretat Mitjana

L'aplicació aplica la desinfecció bàsica d'entrada mitjançant funcions com araaddslashes()per escapar'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

Com es pot atacar:



Un senzill'la injecció ja no funcionarà (perquè es converteix en').

Però els atacants encara poden evitar-ho mitjançant la injecció numèrica (ja que els números no necessiten cometes).
Exemple:

anàlisi de cadena a int
1 OR 1=1

Això encara retorna tots els registres.

3. Alta seguretat

L'aplicació utilitza declaracions preparades (consultes parametritzades) per gestionar de manera segura l'entrada de l'usuari.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

Atac:

Intents com' OR 1=1oUNION SELECTja no funciona.

La consulta tracta totes les entrades com a dades no com a codi SQL.

Tipus d'injecció SQL

Hi ha diferents tipus d'injecció SQL

1. Injecció SQL basada en errors

La injecció SQL basada en errors és un tipus d'injecció SQL en banda on un atacant fa intencionadament que la base de dades generi un missatge d'error. Aleshores, l'atacant analitza aquest missatge d'error per obtenir informació valuosa sobre l'estructura de la base de dades, com ara noms de taules i noms de columnes, que es poden utilitzar per crear atacs més precisos.

Com funciona

Aquest atac s'adreça a aplicacions que revelen errors de base de dades en brut en lloc de mostrar missatges genèrics. En injectar una entrada maliciosa que trenca la sintaxi SQL, els atacants desencadenen aquests errors i obtenen pistes valuoses sobre l'estructura de la base de dades.

cadena a la matriu c
  1. Identifiqueu una entrada vulnerable: L'atacant troba un camp d'entrada com una barra de cerca o un paràmetre d'URL que interactua directament amb la base de dades sense una desinfecció adequada d'entrada.
  2. Injecteu una càrrega útil maliciosa: L'atacant injecta un caràcter especial (com una cometa simple') o una funció que se sap que provoca un error de base de dades.
  3. Analitzar l'error: La base de dades no pot processar la consulta amb format incorrecte retorna un missatge d'error detallat. Aquest missatge pot revelar informació crucial com ara:
    • El sistema de bases de dades (per exemple, MySQL Oracle SQL Server).
    • La versió de la base de dades.
    • S'està executant la consulta SQL completa.
    • Errors de sintaxi específics que es poden utilitzar per comprendre els noms de taules o columnes.
  4. Refina l'atac: Utilitzant la informació recollida del missatge d'error, l'atacant pot refinar la seva càrrega útil per extreure més dades, com ara noms d'usuari i contrasenyes.

Exemple:

Pas 1: configureu el vostre entorn

  • Inicieu DVWA. Normalment s'hi accedeix navegant a un URL comhttp://localhost/dvwaal vostre navegador.
fitxer' loading='lazy' title=
  • Inicieu sessió a DVWA amb les credencials predeterminades:admin/password.
fitxer' loading='lazy' title=
  • Aneu a la pestanya Seguretat DVWA i configureu el nivell de seguretat a baix. Això garantirà que les vulnerabilitats siguin fàcils d'explotar.
fitxer' loading='lazy' title=

Pas 2: Identificar la vulnerabilitat

La pàgina d'injecció SQL té un quadre d'entrada senzill on podeu introduir un ID d'usuari. És probable que la consulta de fons sigui alguna cosa aixíSELECT * FROM users WHERE id = 'user_input'

  • Introduïu un identificador vàlid com1al quadre d'entrada i feu clic a "Envia". Hauríeu de veure els detalls de l'usuari amb ID 1.
fitxer' loading='lazy' title=

Font d'injecció SQL

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • Ara intenta trencar la consulta. Introduïu una cita única'al quadre d'entrada i envia.
fitxer' loading='lazy' title=

La consulta es converteix en:

SELECT * FROM users WHERE id = ''';

Aquí la base de dades veu un pressupost addicional i no sap com completar la consulta.

llista ordenar java

En lloc de mostrar-vos els detalls de l'usuari, l'aplicació retornarà un error SQL (alguna cosa com "Teniu un error en la vostra sintaxi SQL...")

Això s'anomena injecció SQL basada en errors perquè:

  • L'atacant envia una entrada no vàlida (')
  • La base de dades genera un error
  • Aquest error filtra informació útil sobre la base de dades (com el tipus d'estructura del nombre de columnes de la base de dades, etc.)

2. Injecció SQL basada en unions

La injecció SQL basada en la unió és una tècnica on els atacants utilitzen elUNIONoperador per combinar els resultats de dos o mésSELECTdeclaracions en un únic conjunt de resultats. Això els pot permetre extreure informació d'altres taules de la base de dades. ElUNIONL'operador només es pot utilitzar si:

  • Les dues consultes tenen el mateix nombre de columnes
  • Les columnes tenen tipus de dades similars
  • Les columnes estan en el mateix ordre

Operador UNION : ElUNIONL'operador s'utilitza per combinar el conjunt de resultats de dos o mésSELECTdeclaracions.

  • CadascúSELECTdeclaració dinsUNIONha de tenir el mateix nombre de columnes
  • Les columnes han de tenir tipus de dades similars
  • Les columnes han d'estar en el mateix ordre
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Exemple:

Pas 1: En primer lloc, hem de trobar el nombre de columnes de la taula existent al lloc web per injectar la injecció SQL basada en UNION:

La pàgina d'injecció SQL té un quadre d'entrada senzill on podeu introduir un ID d'usuari. És probable que la consulta de fons sigui alguna cosa així

 SELECT * FROM users WHERE id = 'user_input'

Ara intenta trencar la consulta. Introduïu una cita única'al quadre d'entrada i envia.

Si l'aplicació és vulnerable, rebreu un missatge d'error detallat. Pot semblar una cosa així:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

Pas 2: Utilitza elUNIONParaula clau per descobrir el nombre de columnes

Per utilitzar elUNIONparaula clau (un pas següent comú) cal saber el nombre de columnes de la consulta original. Podeu esbrinar-ho fent servir elORDER BYclàusula

comanda arp-a
  • Intenta ordenar els resultats per columna
1: 1 ORDER BY 1. 
  • Envia. Hauria de funcionar.
fitxer' loading='lazy' title=

Font d'injecció SQL

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • Incrementa el nombre:
 1 ORDER BY 2. 

Envia. Hauria de funcionar.

fitxer' loading='lazy' title=
  • Continueu augmentant fins que obtingueu un error. Per exemple1 ORDER BY 4et podria donar:Unknown column '4' in 'order clause'
  • Això vol dir que la consulta té 3 columnes.

3. Injecció SQL basada en cegues

Injecció SQL cega es produeix quan els atacants no poden veure els resultats de la consulta directament a la pàgina web. En canvi, dedueixen informació de canvis subtils en el comportament de l'aplicació o el temps de resposta. Encara que és més lent i tediós que l'SQLi clàssic, pot ser igual d'eficaç.

En lloc de recuperar dades, l'atacant infereix informació observant el comportament de la pàgina web. Això es fa normalment d'una de dues maneres:

  1. SQLi cec basat en booleans: L'atacant injecta una consulta SQL que retorna a veritat o fals resultat. La resposta de l'aplicació web canvia en funció de si la consulta és certa o falsa. Per exemple, la pàgina pot mostrar un missatge diferent o representar un disseny diferent.
  2. SQLi cec basat en el temps: L'atacant injecta una consulta SQL que fa que la base de dades realitzi una acció que consumeix molt de temps (comSLEEP()funció) si es compleix una condició. L'atacant observa el temps que triga a carregar la pàgina per determinar si la condició injectada era certa o falsa.

Exemple:

Imagineu una pàgina d'inici de sessió on introduïu un nom d'usuari i una contrasenya. L'aplicació construeix una consulta SQL com aquesta:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

Una injecció SQL cega implicaria manipular el fitxeruser_inputcamp per fer una pregunta a la base de dades.

En lloc d'obtenir una resposta directa, l'atacant podria provar alguna cosa com això:

user_input = 'admin' AND 1=1; --

Si la pàgina es carrega normalment, l'atacant ho sap1=1és a veritat declaració.

user_input = 'admin' AND 1=2; --

Si la pàgina mostra un error o es comporta de manera diferent, l'atacant ho sap1=2és a fals declaració.

fitxer' loading='lazy' title=

Mitjançant una sèrie d'aquestes preguntes veritables/falses, un atacant pot endevinar i extreure informació sistemàticament un personatge a la vegada. El procés es pot automatitzar per endevinar tot, des de noms de taules fins a contrasenyes d'usuari.

Impacte dels atacs d'injecció SQL

  • Accés no autoritzat a dades sensibles : Els atacants poden recuperar informació financera personal o confidencial emmagatzemada a la base de dades.
  • Problemes d'integritat de les dades : Els atacants poden modificar la supressió o la corrosió de dades crítiques que afecten la funcionalitat de l'aplicació.
  • Escalada de privilegis : Els atacants poden evitar els mecanismes d'autenticació i obtenir privilegis administratius.
  • Temps d'inactivitat del servei : La injecció SQL pot sobrecarregar el servidor provocant una degradació del rendiment o fallades del sistema.
  • Danys a la reputació : Un atac reeixit pot perjudicar greument la reputació d'una organització provocant una pèrdua de confiança del client.

Prevenció d'atacs d'injecció SQL

Hi ha diverses pràctiques recomanades per prevenir atacs d'injecció SQL:

1. Utilitzeu declaracions preparades i consultes parametritzades

Les declaracions preparades i les consultes parametritzades asseguren que les entrades de l'usuari es tracten com a dades i no com a part de la consulta SQL. Aquest enfocament elimina el risc d'injecció SQL.

Exemple en PHP (utilitzant MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. Utilitzar procediments emmagatzemats

Els procediments emmagatzemats són consultes SQL predefinides emmagatzemades a la base de dades. Aquests procediments poden ajudar a prevenir la injecció SQL perquè no construeixen consultes SQL de manera dinàmica.

emojis d'iphone a Android

Exemple:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. Validació d'entrada de llista blanca

Assegureu-vos que les entrades de l'usuari estiguin validades abans de ser utilitzades en consultes SQL. Només permeteu determinats caràcters i patrons, com ara l'entrada alfanumèrica, per a camps com ara noms d'usuari o adreces de correu electrònic.

4. Utilitzeu marcs ORM

Frameworks de mapatge relacional objecte (ORM) com Hibernar o Marc de l'entitat pot ajudar a prevenir la injecció SQL mitjançant la gestió automàtica de la generació de consultes impedint la construcció de consultes dinàmiques.

5. Restringeix els privilegis de la base de dades

Concediu als usuaris els permisos mínims de base de dades necessaris. Assegureu-vos que les aplicacions només puguin realitzar les accions necessàries (per exemple, SELECT INSERT) i restringir permisos com DROP TABLE o ALTER.

6. Tractament d'errors

Configureu la base de dades i l'aplicació per no mostrar missatges d'error detallats a l'usuari. En lloc d'això, registreu els errors internament i mostreu missatges d'error genèrics als usuaris finals.