一:SQL注入漏洞介绍
SQL注入攻击包括通过输入数据从客户端插入或注入SQL查询到应用程序,一个成功的SQL注入攻击可以从数据库中获取敏感数据,修改数据库数据,执行数据库管理操作,在某些情况下能对操作系统发布命令,SQL注入攻击是一种注入攻击,它将SQL命令注入到数据层输入,从而影响执行预定义的SQL命令,由于用户的输入,也是SQL语句的一部分,所以攻击者可以利用这部分可以控制的内容,注入自己定义的语句,改变SQL语句执行逻辑,让数据库执行任意自己需要的指令
二:修复建议
1:所有查询语句都是用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中,当前几乎多有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入
2:严格限制变量类型,比如整型变量就采用intval()函数过滤,数据库中的存储字段必须为int型
3:对进入数据库的特殊字符(' " \ `等)进行转义处理,或者编码转化
4:限制数据长度,能在一定程度上防止比较长SQL注入语句,网站每个数据层编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过
5:避免网站显示SQL错误信息,比如类型错误,字段不匹配等,防止攻击者利用这些错误信息进行一些判断
三:注入点判断
注入的原理很简单,注入的姿势也有很多种,当然 我们如何寻找注入点也变成了重中之重。登录框 搜索框一切可能与数据库存在交互的功能点都是我们要进行测试的对象,下面介绍几点常见判断注入的方式
1:单引号 双引号 拼接符等 查看页面是否报错 一个 两个 三个进行不断尝试 如果出现页面回显错误 随后就进行闭合 能成功闭合那么就存在注入
2:进行算数运算 如id=1/1 与id=1/0的区别 存在明显的区别则说明存在注入点 且为数字型的
3:id=1 and sleep(5)通过查看页面响应的时间来进行判断 有个别案列也是两个单引号无法进行闭合 但是构造 id=1'and 1='1的时候又成功闭合了 总而言之就是多进行尝试
四:sql注入的骚姿势
1:联合查询
首先判断是整数型还是字符型 随后采用order by来进行字段的判断 一般用二分法1,3,5逐渐递增
输入为 order by 4的时候 页面回显出错 可以判断出字段数为三个
重点来了 使用union select来进行查询信息 首先查看有回显的字段数 输入?id=-1'union select 1,2,3--+当然 我们需要使得前面的条件报错 这样才会显示后面的查询信息
查看回显我们知道在字段 2 3的位置有回显的 这样我们就可以对数据进行查询了id=1?union select 1,database(),user()--+ database()表示当前数据库 user()表示当前用户 具体情况具体分析数据库类型不一样 查询使用的函数不一样 就比如orcale当前用户为user mysql数据库为user()
2:报错注入
当我们在判断注入点的时候 如果回显的信息里面出现了关于数据库的错误的信息 我们不妨可以试试使用报错注入 将我们需要的信息获取出来,当然 我们可以根据报错信息来对数据库的类型进行判断
这种出现一长串的英文报错信息 一般都是mysql数据库
这种提示在某处出现转换错误 且带中文的一般为 sql sever数据库 等等 这些信息都是我们自己需要在平常渗透测试中收集的
不同的数据库在进行报错注入的时候用到的函数也是不一样的 以mysql数据库为例子 常用的报错语句由 floor() updatexml() extractvalue()等函数
在这里我们使用updatexml()来构造poc进行测试,一个单引号报错 两个单引号正常
构造poc ?id=1'and+updatexml(1,concat(0x7e,database()),1)--+
0x7e也是就是页面显示出来的~ 为了能让我们更加方便的找到查询的信息
3:盲注
盲注分为时间盲注与布尔盲注 归根结底 盲注无非就是判断语句 if(), case when与mid() left()等查询函数的结合利用
时间盲注与布尔盲注的区别就在于是否使用函数sleep() 两者区别也不大 平常的渗透测试中也比较喜欢使用布尔盲注 很少用到时间盲注无非在用sqlmap跑的时候 才会发现 哦 原来sqlmap是用的时间盲注啊 因为个人时间盲注用的比较少 所以呢 我们主要介绍布尔盲注
同样也可分为整数形的布尔盲注与字符型的布尔盲注 话不多说 上案例看看吧
字符型布尔盲注
俗话说的好造车先造轮子 我们也要构造最基础的车轮(poc)一般使用 ?id=1'and+1='1与?id=1'and+1='0两种车轮进行对比,当1=1的时候回显正常 1=0的时候回显不正常 就这样一个最基础的车轮就构造好了
接下来呢 就是将车轮变形成为汽车了 要让他能在burp中成功跑起来 我们将在1='1找个点上展开变形 使用我们的if语句来构造出一个能查询到我们想知道的信息的语句 最终poc ?id=1'and+if(mid(user(),1,1)='a',1,0)='1 =a与!=a的时候页面回显是不一致的 说明我们的车成功的造出来了 后面就丢进burp让他跑起来就行
整数型布尔盲注也差不多 一般会在参数 ?id=1后面直接构造poc 比如?id=1/1与?id=1/0直接进行对比 在使用if() mid()函数进行变形
4:堆叠注入
在SQL中,用分号(;)表示一条sql语句的结束,堆叠注入呢就是在上一条语句结束后继续构造下一条语句。堆叠注入与联合查询最主要的区别就是 联合查询union或union all执行的语句类型是有限的,而堆叠注入可以执行任意的语句。然而 堆叠注入也是有局限性的 堆叠注入并不是每一个环境都可以执行的,可能受到API或者数据库引擎不支持的限制。下面就上实例吧
可以看到 我们使用order by得知数据字段为3个
这时候 我们使用一个分号(;)结束上一个sql语句 随后添加一个sql语句
为了验证 账号是否成功被添加进去 我们来到42关进行登陆 输入账号密码后成功登陆 说明我们插入的数据被保存到数据库中了
5:二次注入
二次注入怎么说呢 也就是用户的输入的数据 开发者就认为数据是可信的,在下次进行查询的时候 直接从数据库中取出了脏数据,没有进行下一步的检验和处理,这样就会导致造成SQL的二次注入,当然二次注入的条件还是很苛刻的 目前为止 作者是还没碰到过
如下 我们现在admin账号的密码是admin 现在我们通过二次注入 将admin的密码给修改
注册一个账号为admin'# 密码随便设置
我们登录admin'#的账号 随后进行密码修改 将密码修改为000000
修改后 我们发现admin账号的密码变成了000000 admin'#账号的密码没变
就这样 我们成功修改了admin用户的密码 因为二次注入的条件十分苛刻 碰到的概率非常低 这里就不做详细的讲解了
以上简单的介绍了一下sql注入的基本类型以及原理 随后会着重介绍sql注入绕过各种waf的操作,同时也会附上我个人平时进行渗透测试的案例以及poc供大家参考