Web渗透_SQL盲注






各类DBMS数据库管理系统默认集成安装了许多库函数、存储过程,这都可以利用。

所有的渗透前提都要了解正常业务流程,也就是说正常的登录操作也要了解。




SQL盲注(布尔型、延时型)

程序员屏蔽了错误回显,无法根据报错信息判断,页面只会显示真假两种状态。






布尔型注入



(1)首先判断注入点的POC形式

(2)length()函数猜解数据库名长度

(3)substr()确定数据库名具体内容



如下分别为真、假:

happysneaker.com

happysneaker.com


再次注意 $id 可能的三种方式:

happysneaker.com


测试,看来后台是 '$id' 这种形式:

happysneaker.com


所以思路也就有了:


① 通过length(str)函数,猜解数据库名的长度=4

happysneaker.com



② 结合substr(str,num1,num2)函数猜解数据库名的具体内容:

happysneaker.com


happysneaker.com


但是这样未免太麻烦,我们因为不知道具体内容是什么,只能暴力破解,所以可以考虑结合 ASCII()函数:

happysneaker.com


happysneaker.com

happysneaker.com

所以得出此次求解的这个字符在64——127之间,继续二分法求解,得到原来第一个字符为 d :

happysneaker.com


重复四次上述操作,得到数据库名=dvwa,可以发现SQL盲注真的是挺麻烦。

happysneaker.com


注意: 核心思想在报错与不报错之间的比较。




延时型注入


(1)猜解数据库名if(case,ret1,ret2)、length()、sleep()等延时函数是核心

(2)benchmark(count,md5('test'))  运行count次后面的内容,肯定会使用较长时间才返回


 

还是猜解数据库名来说,延时注入先需要 if函数:

happysneaker.com


happysneaker.com


然后配合sleep()休眠函数,意思为休眠多少秒再运行程序:

happysneaker.com

happysneaker.com



将length()、if()、sleep()三个函数配合使用,如果数据库名长度=4,那么延时5秒钟返回,这个为真,否则为假:

happysneaker.com

happysneaker.com



除此之外还有benchmark()函数:

happysneaker.com



happysneaker.com


如下的意思就是:如果数据库名长度=4,那么就运行500w次对test这个字符串的md5加密,肯定是会耗费比较长的时间的,否则就立马返回了,如下对比:

happysneaker.com

happysneaker.com


因为盲注真的挺麻烦,所以一般这里就需要用到工具,比如sqlmap.py。

注意substr()与mid()函数功能类似。ascii()与ord()函数功能类似。




       上面是low等级的操作原理,medium等级由于可以修改id然后post提交所以也不难,high等级通过数据包观察可以看到每次提交的id包含在了cookie中一起进行了提交 所以使用sqlmap的时候除了添加cookie参数还要添加一个level函数并且level设置为2,impossible等级无法注入。


Low 等级下的 sqlmap.py 注入步骤:

获取数据库名:

happysneaker.com


获取表名:

happysneaker.com


获取列名:

happysneaker.com


dump出用户名、密码:

happysneaker.com




总结


分析源码,同SQL回显注入一样,都是进行了SQL语句的参数化,对输入进行了数据类型判断以及字符过滤,所以只要是SQL注入,修复办法主要是参数化SQL语句


happysneaker.com


② BOOL注入和延时注入的共同点?

都是一个字符一个字符的判断




扩展:



情景一:

可能注意到了上一篇文章用的方法都是基于 information_schema 元数据库操作的,但是往往现实是我们没有这个库的访问权限。而且很多时候 union、order by 也被过滤掉。所以需要根据情况灵活尝试。


这时候我们就需要猜解了。思路是:猜解列名——猜解表名——猜解数据库名


① 猜解列名 : ' and qqq=null --   或者  1' or qqq is null --  都一样的, null 不理解你换成 is not null 也可以,一样的。

qqq 是随便填写的列名,如果表里真有 qqq 这个列,那么返回的数据包是比较大的,如果没有这个列 ,则会提示 

Unknown column 'qqq' in 'field list'

因此我们通过这个可以无限猜解列名,结合BurpSuite自动化猜解,能得到比较准确的所有列名。


② 得到列名可以继续猜解表名,思路一样:

' and 表名.user is null -- 

同样Burp自动注入得到所有表名。


③ 猜解库名:  ' and 库名.表名.列名 is null -- 




情景二:

当数据库可写:

比如我们如果破解不了密码,就可以自己增加一条用户名密码然后使用。总之增删改查灵活使用。


还有SQL server早期有个存储过程的漏洞,cp_cmdshell 。








Web安全技术分享
请先登录后发表评论
  • 最新评论
  • 总共0条评论