【漏洞】SQL注入漏洞(一)
SQL注入漏洞成因
SQL注入漏洞存在的成因主要是:用户将自己可控的输入内容拼接到了源代码中的SQL语句中,并且系统将拼接后的SQL语句发送给了后台数据库执行。
SQL注入可以导致:信息泄露、木马上传等。
常见的存在注入功能场景
常见的SQL注入场景有用户认证场景和搜索场景。
理论上存在用户可控输入,且与后台数据库有交互的地方的都可能存在SQL注入,都需要根据“代码与数据分离”原则,做好SQL注入防护。
用户认证场景
用户认证场景下的SQL语句如下示例,可以利用“万能密码”绕过认证。
MySQL示例:SELECT * FROM user WHERE username = '$user' AND password = '$pwd'
username处拼接示例:a' or 1=1#
拼接后的语句:SELECT * FROM user WHERE username = 'a' or 1=1#' AND password = 'pwd123'
#号将后半句语句注释掉,实际执行的就是前半句,并且or 1=1是一个永真条件,最后数据库返回一定是一个为真的结果,导致绕过认证。
“or 1=1”也被称为“万能密码”
搜索场景
搜索场景下的SQL语句如下示例,可以利用联合查询(union select)造成信息泄露。
MySQL示例:select * from books where bookname like '$key%'
拼接示例:a%'/**/union/**/select/**/1,user,pasword/**/from/**/webapphacking.users#
拼接后的语句:select * from books where bookname like 'a%' union select 1,user,pasword from webapphacking.users#%'
拼接后的语句相当于执行了两个查询语句:
- 第一个查询:查询a开头的books字段的内容。
- 第二个查询:查询webapphacking数据库users表中user和pasword字段的内容。
举例为HACKME:2靶机的注入语句,其中“1,user,pasword”是为了配合前一个查询,前一个查询返回三个字段内容。
SQL注入点判断
同样以HACKME:2靶机举例。
构造拼接语句:a%' and '1'='1'#
正常返回搜索以a开头的书名。
构造拼接语句:a%' and '1'='2'#
返回结果为空。
通过两次结果的对比,可以判断执行了拼接的语句,存在注入点。
有些注入场景下可能肉眼无法直接判断是否有差异的,也可以利用burpsuite观察返回页面的大小来判断。
常见的SQL注入攻击方法
推荐的SQL注入练习试验环境是Sqli-Lab。
报错注入
主要利用数据库返回的报错信息进行SQL注入,要求网站会将数据库的报错信息返回到前端的页面上。
据目前了解,现在利用报错进行注入的应该非常少,不过不排除有一些刁钻的注入角度。
常用到的数据库函数:updatexml(),extractvalue()
示例:'or updatexml (1,concat(0x282b,version(),0x282b),1)#
示例:extractvalue( 1,concat(0x2b,version()))
利用报错会返回数据库版本信息,在“version()”位置替换注入语句。
concat()函数的作用的用于分隔内容,有时返回内容较多,利用指定字符分隔返回的内容,方便肉眼观察及后续处理。concatws()也是同样作用。
盲注
盲注主要是指网站不将返回结果直接显示在页面上,只能通过网页的变化来判断数据库范围结果是为真还是为假。
盲注有基于时间的和基于布尔的两种。
- 布尔型盲注
利用if判断条件,结合length()/substr()/mid()/ascii()/ord()等函数,猜测数据库名或字段内容等。 - 时间型盲注
在布尔型基础上,利用sleep()函数,让数据库延时返回结果。
当无论返回结果真假,页面显示均相同,则需要通过返回时间来进行判断。
SQL语句示例:if( ascii( substr(database(),1,1))>115,0,sleep(5))
猜测当前数据库名称第一个字母的ASCII码是否大于115,若是,返回0,若否延迟五秒。
盲注需要掌握“二分法”,可以有效减少盲注时间。
“二分法”关键的几个ASCII码:
- A:65
- Z:90
- a:97
- z:122
- 0:48
- 9:57
联合查询注入(union select)
利用union select让数据库执行返回多个查询结果,并将查询结果回显在页面上。
例:union select 1,2,3 其中2和3是能够显示在页面上的,则union select 1,database(),3
其他注入方法
宽字节注入:当单引号(’)被转义符(反斜杠)转义,且数据库编码为GBK时,存在宽字节注入。
例:?id=1'
,宽字节的格式会在1后面加上 %df
,变成?id=1%df%5c'
(反斜杠的编码为%5c
),而%df%5c
在GBK编码中为“連”字,导致单引号逃逸成功。
cookie注入:当cookie中具备某参数,且该参数可注入,则是cookie注入。
base64注入:客户端会对输入的参数进行base64编码,服务端收到参数后,再进行base64解码后,代入查询语句中执行。
例:?id=1'
base64编码后 ?id=MSc%3d
XFF注入:当PHP使用getenv()函数获取环境变量值,且为对输入值过滤时,通过伪造HTTP请求的头部参数X-Forwarded-for或者Client-ip,可实现注入。
例:x-forwarded-for:127.0.0.1' union select 1,2,3#
还有其他未了解到的。
SQL注入绕过技巧
大小写绕过:and→And,select→SeLeCT
双写绕过:and→aandnd,select→selselectect
编码绕过:将被拦截的关键字进行两次URL编码,and→%61%6e%64→%25%36%31%25%36%65%25%36%34
内联注释绕过:and→/*!and*/,select→/*!select*/
/**/
代替空格:1' and 1=1→1'/**/and/**/1=1 ,1' union select 1,2,3→1'/**/union/**/select/**/1,2,3