vlambda博客
学习文章列表

Web-Sec学习笔记之一:SQL注入

web安全是信息安全中较为重要的一个分方向.一共有如下几点

1.SQL注入 将着重介绍四种SQL注入

(报错注入,联合查询,基于逻辑的盲注,基于时间的盲注)以及它们的原理,和应用范围

2.XSS跨站脚本攻击 将着重介绍四种XSS方式

(反射XSS,存储XSS,Dom-XSS,Flash-XSS)以及它们的原理,和应用范围

3.PHP代码审计 将目前所掌握的几种主流的漏洞类型和审计方法

(逻辑漏洞,sql注入,lfi本地包含,rcs远程命令执行)


这里首先介绍SQL注入

SQL注入攻击是一种很古老的攻击方式了,到现在其实已经有很多完美的解决方案,比如说预编译,比如owasp给出的处理函数

但是由于完整的开发过程中,总会因为各种各样的原因忽略了这些措施,而导致漏洞的存在。

现在,对于SQL注入,普遍来说有4种分类,报错注入,联合查询,基于逻辑的盲注,基于时间的盲注。

简单的说一下分类的依据. 其实这里进行分类,除了数据库本身的原因外,还有配套的脚本语言的关系。

例如:报错注入其实指的就是,在php默认配置mysql等数据,开启错误显示的时候发生的注入。这里的"报错"并不是说,返回了一个错误页面

而是要能够有完整的错误信息,例如"unexpected xxxxx"而不是一片空白(那是由于关闭了错误显示,查询返回了一个null结果)

而盲注就是在关闭错误显示下的注入,像上面提到的单纯关闭错误显示,而返回null结果的注入方法.其实是属于逻辑盲注的。

在没有错误显示的情况下,只能通过返回的页面是否为null,来判断某个表达式是否正确,按每位来注入出结果。

而在对页面都做了处理的情况下(可能直接被重定向或者其他处理)这时就只能通过执行表达式的时间来判断注入的结果

也就是基于时间的盲注。

联合查询其实与其说是一种SQL注入的类型,不如说是利用union语句,直接返回多个查询结果,更妥当的说法是一种注入技巧。

联合查询中,用到的是union语句,来执行多个select查询.

对于union select来说,最重要的是确定字段的长度,最后根据显示位来进行注入,得出结果

可以使用order by的方法来确定字段长度,order by a,如果返回了逻辑正确,那么说明实际字段>=a

在order by语句不能使用时,也可直接用如下语句来测试.最大有多少个null而不报错,就有几个字段,就和上述语句同等的效果。

union select null,null,.... from *

union select 1,2,3,4,5,6,7,8,9,10,.. from *

这样通过前面构造一个错误的查询语句,就可以看到这个页面用到了哪些显示位,再把对应的显示位改成需要查询的字段名.

比如

id=-1 union select 1,username,password from admin

联合查询比较简单,属于一种技巧,再加上waf等防护方案对其比较敏感,实际用途较窄,所以一笔带过。

报错注入

报错注入是一种在php,或者其他脚本语言,开启了错误显示的情况下发生的注入.

其中的"报错"的核心含义是,利用一些函数发生错误时,对于传递的参数(往往是我们构造的一个表达式)会返回其错误信息,而且这个错误信息是经过查询后的.

这样,我们就能比较方便的获得一个查询结果,而不用依次猜解。

较为常用的4个payload //有待补充

其中,利用和XML有关函数的有两个,Updatexml和Extractvalue

Updatexml:and 1=(updatexml(1,concat(0x3a,(select user())),1));

该函数一共接受三个参数

Extractvalue:and extractvalue(1, concat(0x5c, (select user())));

该函数一共接受两个参数

利用和数值类型有关的函数有两个,floor和pow

//感谢音符牛给出了最简短的payload

floor:and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

pow:and select pow(2,~ x) from (select user()x)a;

基于逻辑的盲注

在网站默认关闭错误信息的时候,如果这时并没有做其他的处理,我们可以通过逻辑表达式来进行盲注.

大概的原理是:如果我的逻辑表达式是正确的,那么整个sql查询语句一定会返回结果,那么网站显示了正确的内容

通过这个原理,我们可以通过注入依次获取每个字符,由于过程繁琐,很多时候这一过程由自动化工具实现.

为了节约时间,在mysql中可以利用正则表达式,大致确定某个字符的范围

and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-n]' LIMIT 0,1)

通过这样的方式,可以大致确定某个位是字母还是数字,这样就有了大致的ascii范围,然后可以继续猜解,语句类似于

AND ascii(substring((SELECT password FROM users where id=1),1,1))=49

对于逻辑盲注来说,主要是为工具提供了可行性,可能还有一些隐藏的技巧,我没有深入的挖掘。

基于时间的盲注

基于时间的盲注,一般是在条件更为苛刻的情况下,例如最终进行了跳转,使用的一种注入的方式。

其原理是利用if语句,在逻辑表达式成立的情况下,执行某一个延时的函数,这样,就可以通过最后返回的时间,来判断逻辑表达式的正确与否

这里举例使用的是benchmark函数,它可以执行x次传入的第二个参数所表示的函数

BENCHMARK(count,expr)
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。

IF表达式

IF(expr1,expr2,expr3)

如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。

于是,我们可以构造如下语句,如果成立执行延时函数,否则为Null

select if(substring(current,1,1)=char(11),benchmark(5000000,encode('msg','by 5 seconds')),null) from dbname

对于过滤引号的情况:
可以用0x十六进制字符串来代替 '这是一个字符串' 来绕过某些引号过滤的情况
xx=char(x,x,x)这样也是可行的
如果注入点本身就是字符型注入点。
那么如果这个时候数据库是gbk编码,就可以使用宽字节来吃掉转义的/或者是多余的单引号

外传:谈谈所谓万能密码

万能密码"这个说法在多年前就开始流行了,这个说法并不恰当,更像是脚本小子们不懂原理,却往上粘贴,以为"万能"的一种注入技巧

这里,我们对一种情形下的安全逻辑进行讨论。

设想一下一个登陆界面,没有经过任何的数据过滤,其执行的sql语句大致如下

$flag=select * from user where username='输入点' and password='输入点';

这种情况下,我们可以控制上述的两个输入点,一般网上流传的万能密码,是这样的形式

'or 1=1# 在这里,or后连接的一个恒等语句,绕开了原本的逻辑结构,实现了登陆。

但是,我们肯定不止停滞于script boy们的阶段,让我们一起来构造一下更好看,更短的payload。

'||1=1#这样也是可行的,而且缩短了一个空格。我们再进一步尝试

'||1# 这样也是可以的,1这个常数也可以当做一个单独的表达式,还能缩短么?

'&1# 这里开始就比较奇怪了.. 为什么这样的方法也可以绕开逻辑呢?

详细的原理参见阿里ctf2014的第一题.是关于sql语句的逻辑的。

这里用来判断的flag,是根据sql语句返回的结果进行判断的。如果没有查询到结果(不符合结果,那么返回的必然是false,也就是0

然而,只要>0的返回值,都会被判断为是true。这里就产生了逻辑漏洞。如果我们直接对其进行计算操作

无论是%模运算,还是*乘法运算,或者是其他的普通运算符或逻辑运算符,都会绕过原本的逻辑。

因此,最终的payload只有4个字符。

当然,这种情况只适用于上述的逻辑过程。为了避免这个漏洞的发生,一是要做好过滤,或者干脆预编译

另一种方法是从业务逻辑上解决问题,如,我们先根据提供的username进行查询,把查询的结果里的password和提交的password进行对比

这样,就可以从根本上消除这个逻辑问题。

总结

SQL注入经过十几年的风吹雨打,至今仍然是owasp top10威胁中比较严重的一个。不仅仅是程序员对规范的不遵守和自身代码习惯差。

数据库技术的发展,新函数新功能的引入,同样带给了它以新的生存土壤,值得我们的关注。

https://f002.backblazeb2.com/

一篇很老的文章

但是观点很清晰,值得静下心来阅读。