UNION SQL Injection

1

Estoy tratando de demostrar la inyección SQL con una consulta UNION pero no estoy obteniendo resultados.

Este es el código C # y la base de datos es SQL Server 2008 R2:

        string cString = "server=.\sqlexpress; database=testDB; trusted_connection=true";
        SqlConnection conn = new SqlConnection(cString);
        conn.Open();

        string sql = "select * from Users where UserName='" + userName + "' and Password='" + password + "'";
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = sql;

        SqlDataReader reader = cmd.ExecuteReader();

        StringBuilder sb = new StringBuilder(1024);

        while (reader.Read())
        {
            for (int i = 0; i < reader.FieldCount; i++)
            {
                sb.Append(" " + reader.GetName(i));
                sb.Append(": ");
                sb.Append(reader[i]);
            }
            sb.Append("<br />");
        }
        dataLabel.Text = sb.ToString();

Tengo un cuadro de texto de nombre de usuario y contraseña y la entrada se pasa a este método.
Intenté lo siguiente pero ningún resultado:

'union select * from products -

la tabla Usuarios y la tabla Productos tienen tipos de columna idénticos (int, nvarchar, nvarchar).
¿Puede alguien ayudar? ¿Qué me estoy perdiendo?

    
pregunta Test Er 13.01.2013 - 02:04
fuente

2 respuestas

3

Para un trabajo de declaración de selección de unión, ambas declaraciones de selección deben devolver el mismo número de columnas. Esto se debe a que una selección de unión está concatenando ambas declaraciones de selección y devolviéndolas como un conjunto de datos.

Si la primera tabla, Users tiene 4 columnas, la vulnerabilidad se vería así:

select * from Users where UserName='' union select producs.id,products.name,products.price,products.quantity,products from products-- ' and Password=''"

En este caso, la primera declaración de selección no devolverá un valor porque no hay un registro en la base de datos donde UserName='' , donde la segunda declaración devolvería información de la tabla de productos. Aunque un exploit más probable sería seleccionar las contraseñas de la tabla de Usuarios en la posición del nombre de usuario para que se imprima con reader.GetName(i) .

Otra forma de explotar este problema es proporcionar sus propios datos para devolverlos:

select * from Users where UserName='' union select 1,'admin','password','ADMINISTRATOR','[email protected]' -- ' and Password=''"

Si los datos devueltos por la consulta se utilizan en una función sensible, como poder contaminar una variable utilizada en la evaluación de código o archivo.

¿Cómo sabes cuántas columnas tiene la primera consulta?
Uso intrusos eructos para iterar sobre todas las posibilidades y filtrar las solicitudes sin errores.

... o simplemente puede usar sqlmap

    
respondido por el rook 13.01.2013 - 07:22
fuente
0

Mientras realiza las pruebas, ¿por qué no agregar una declaración de depuración que registre su consulta SQL antes de ejecutarla?

Luego intente ejecutarlo en su base de datos directamente y vea qué mensaje de error devuelve la base de datos (si corresponde).

Si no hay un escape automático inadvertido de ' en su marco, parece su consulta:

string sql = "select * from Users where UserName='" + userName + "' and Password='" + password + "'";

se convierte en:

 string sql = "select * from Users where UserName='' union select * from products --' and Password=''";

¿Puede verificar que aparezca una cadena como esta en su registro (que su marco no haya escapado inadvertidamente ' caracteres)?

¿Puedes ejecutar esa cadena SQL específica? ¿Devuelve un mensaje de error para sus esquemas / tablas específicos? (No programo en .NET, utilizo el servidor SQL o tengo su base de datos (tiendo a usar la pila de linux; por ejemplo, postgresql).)

Pero ejecutando en una base de datos de muestra que tenía donde probé una UNION de dos tablas como SELECT * FROM table_a where name='' union select * from table_b , recibo un error de mi DB: SELECT a la izquierda y derecha de la unión no tiene el mismo número de columnas de resultados. Mi tabla_a tenía 7 columnas y la tabla_b tenía 11 columnas. Por lo tanto, una unión de las 7 columnas de table_a y las 11 columnas de table_b no funcionará.

Esto tiene sentido si busca lo que UNION SQL hace:

  

El operador UNION se usa para combinar el conjunto de resultados de dos o más declaraciones SELECT.

     

Observe que cada instrucción SELECT dentro de UNION debe tener el mismo número de columnas. Las columnas también deben tener tipos de datos similares. Además, las columnas en cada instrucción SELECT deben estar en el mismo orden.

     

PS: Los nombres de columna en el conjunto de resultados de un UNION siempre son iguales a los nombres de columna en la primera instrucción SELECT en UNION.

Así que tienes que adivinar el esquema y asegurarte de que coincida. Es decir, si la consulta SQL original tenía un select * from Users , y las columnas de Usuarios son user_id (INT), UserName (VARCHAR), password (VARCHAR), debe asegurarse de que UNION solicite tres campos específicos que tengan tipos de datos int, VARCHAR y VARCHAR que están presentes en la segunda tabla. Además, si no desea obtener resultados de la primera consulta, es posible que desee agregar un AND 1=0 a su cláusula WHERE .

    
respondido por el dr jimbob 13.01.2013 - 11:08
fuente

Lea otras preguntas en las etiquetas