Artículos web de ataque y defensa de infiltración: inyección SQL en términos simples

1. Antecedentes

Jingdong SRC (Security Response Center) incluye una gran cantidad de vulnerabilidades de inyección SQL enviadas por sombreros blancos externos. La mayoría de las vulnerabilidades son causadas por el empalme de declaraciones SQL y el uso inadecuado de Mybatis.

2 Inspección manual

2.1 Conocimiento previo

Hay una importante base de datos del sistema information_schema en mysql5.0 y superior A través de esta base de datos, se puede acceder a metadatos como el nombre de la base de datos, el nombre de la tabla, el nombre del campo, etc., existentes en mysql. Hay tres tablas en information_schema que se convierten en la clave para la construcción de inyección sql.

1)infromation_schema.columns:

  • nombre de la base de datos table_schema
  • nombre_tabla nombre de la tabla
  • nombre_columna nombre de columna

2)información_esquema.tablas

  • nombre de la base de datos table_schema
  • nombre_tabla nombre de la tabla

3)information_schema.schemata

  • schema_name nombre de la base de datos

Inyección de SQL Funciones SQL de uso común

  • length(str) : devuelve la longitud de la cadena str
  • substr(str, pos, len) : intercepta los caracteres de longitud len desde la posición de pos y los devuelve. Tenga en cuenta que la posición pos aquí comienza desde 1, no desde 0 de la matriz
  • mid(str,pos,len) : igual que arriba, interceptar la cadena
  • ascii(str) : Devuelve el valor del código ASCII del carácter más a la izquierda de la cadena str
  • ord(str) : convierte carácter o tipo booleano a código ascll
  • if(a,b,c): a es una condición, a es verdadera, devuelve b, de lo contrario devuelve c, como if(1>2,1,0), devuelve 0

2.2 Tipo de inyección

2.2.1 Clasificación de los tipos de parámetros

  • Inyección de enteros
    Por ejemplo, ?id=1, donde id es el punto de inyección y el tipo es int.

  • Inyección de caracteres
    Por ejemplo, ?id=”1”, donde id es el punto de inyección y el tipo es un carácter, y se deben considerar las comillas en la instrucción sql de back-end.

2.2.2 Clasificación de los métodos de inyección

  • nota ciega
    • Nota booleana ciega: el valor booleano después de la ejecución de la declaración solo se puede inferir de la devolución de la aplicación.
    • Nota de tiempo ciego: la aplicación no tiene un eco claro y solo se puede evaluar mediante el uso de una función de tiempo específica, como suspensión, punto de referencia, etc.
  • Inyección de error: la aplicación mostrará todo o parte del mensaje de error
  • Inyección de pila: algunas aplicaciones pueden unirse y luego ejecutar varias declaraciones a la vez
  • otro

2.3 Pasos de detección manual (inyección de caracteres como ejemplo)

// sqli vuln code
Statement statement = con.createStatement();
String sql = "select * from users where username = '" + username + "'";
logger.info(sql);
ResultSet rs = statement.executeQuery(sql);
// fix code 如果要使用原始jdbc,请采用预编译执行
String sql = "select * from users where username = ?";
PreparedStatement st = con.prepareStatement(sql);

Use el jdbc original no precompilado como demostración. Tenga en cuenta que los parámetros de la instrucción SQL en esta demostración están entre comillas simples.

2.3.1 Determinación del punto de inyección

Para la inyección de tipos de caracteres, las comillas simples generalmente se prueban primero para determinar si las comillas simples se empalman en la declaración SQL. Se recomienda utilizar la extensión del navegador harkbar como herramienta de prueba manual. https://chrome.google.com/webstore/detail/hackbar/ginpbkfigcoaokgflihfhhmglmbchinc

Una página normal debería verse así:

Agregar comillas simples después de admin hace que no se muestre información. El motivo es que la ejecución de back-end sql informa un error, lo que indica que las comillas están empalmadas en la instrucción SQL.

select * from users where username = 'admin' #正常sql
select * from users where username = 'admin'' #admin'被带入sql执行导致报错无法显示信息

2.3.2 Juzgar el número de campos

MySQL usa order by para ordenar, no solo el nombre del campo sino también el número de serie del campo. Por lo tanto, se puede usar para juzgar el número de campos en la tabla.Si el orden por excede el número de campos, se informará un error. 

Determinar el número de campos.

Cuando el orden por supere los 4, se informará de un error, por lo que esta tabla tiene un total de cuatro campos.

Sentencia SQL ejecutada por el backend

select * from users where username = 'admin' order by 1-- '

Aquí reemplazamos el valor de nombre de usuario original admin con el orden de admin por 1 —+, donde la comilla simple después de admin se usa para cerrar las comillas frontales en la declaración sql original, y —+ se usa para anotar las comillas posteriores en la declaración sql . La función principal del signo + después de - es proporcionar un espacio Se requiere un espacio después de un comentario de una sola línea en la instrucción SQL, y el + se decodificará como un espacio.

2.3.3 Determinar la posición del eco

Se utiliza principalmente para ubicar la posición del campo SQL de back-end que se muestra en el front-end y se determina mediante una consulta conjunta. Tenga en cuenta que los campos antes y después de la consulta conjunta deben ser coherentes, por lo que hacemos el segundo paso.

Como se puede ver en la figura a continuación, las posiciones de campo consultadas y repetidas por el backend son de 2 y 3 dígitos.

Los campos después de la consulta conjunta pueden ser arbitrarios. Esta vez, los números del 1 al 4 se usan de manera intuitiva y conveniente.

2.3.4 Uso de la biblioteca information_schema para lograr la inyección

La función group_concat() se usa para concatenar resultados de consultas en cadenas.

  • Consultar la base de datos existente

  • Ver tablas en la base de datos actual

  • Ver campos en una tabla específica

  • Use la información anterior para leer el nombre de usuario y la contraseña en la tabla de usuarios

3 Detección automatizada

3.1 uso de sqlmap

sqlmap es compatible con python2 y python3, y puede detectar automáticamente varias inyecciones y casi todos los tipos de bases de datos.

3.1.1 Comandos comunes

-u 可能存在注入的url链接
-r读取http数据包
--data 指定post数据
--cookie 指定cookie
--headers 指定http头 如采用token认证的情况下
--threads 指定线程数
--dbms 指定后端的数据库
--os 指定后端的操作系统类型
--current-user 当前用户
--users 所有用户
--is-dba 是否是dba
--sql-shell 交互式的sqlshell
-p指定可能存在注入点的参数
--dbs 穷举系统存在的数据库
-D指定数据库
--tables 穷举存在的表
-T指定表
--column 穷举字段
-C指定字段
--dump dump数据

Detección directa
donde --cookie se usa para especificar una cookie, --batch se ejecuta automáticamente y --dbms especifica el tipo de base de datos

Resultados de la prueba

Leer la base de datos existente en el sistema -
dbs lee la base de datos bajo el usuario actual

Lea la tabla en la biblioteca especificada
-D java_sec_code --tables

volcar los datos de la tabla de usuarios
-D java_sec_code -T usuarios --dump

4 Avanzado

4.1 Inyección de Mybatis

1) El uso incorrecto de $ conduce a la inyección  

//采用#不会导致sql注入,mybatis会使用预编译执行
@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);
//采用$作为入参可导致sql注入
@Select("select * from users where username = '${username}'")
List<User> findByUserNameVuln01(@Param("username") String username);

2) Empalme de consultas difusas

//错误写法
<select id="findByUserNameVuln02" parameterType="String" resultMap="User">
select * from users where username like '%${_parameter}%'
</select>

//正确写法
<select id="findByUserNameVuln02" parameterType="String" resultMap="User">
select * from users where username like concat(‘%’,#{_parameter}, ‘%’)
</select>

3) orden por inyección

Si #{} se usa después de order by, se informará un error, porque #{} agrega comillas de forma predeterminada, lo que hará que el campo no se encuentre y se informará un error.

//错误写法
<select id="findByUserNameVuln03" parameterType="String" resultMap="User">
select * from users
<if test="order != null">
order by ${order} asc
</if>
</select>
//正确写法 id指字段id 此表字段共四个 所以id为1-4
<select id="OrderByUsername" resultMap="User">
select * from users order by id asc limit 1
</select>

Las pruebas anteriores se realizan localmente, no realice pruebas de penetración sin autorización

5 Artículos y materiales recomendados

manual de slqmap: https://octobug.gitbooks.io/sqlmap-wiki-zhcn/content/Users-manual/Introduction.html
explicación detallada de la inyección de sql: http://sqlwiki.radare.cn/#/

Autor: Luo Yu (Equipo de seguridad logística)

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/5569859
Recomendado
Clasificación