Tips
1 | 常见URL编码: |
SQL语句举例:
select username from users where id=”1” order by id;
order by : 以列名进行排序,如这里排序的标志是id,同时也可以用数字来代替列名的顺序,如下:
select username from users where id=”1” order by 1;
这两种方式所展示的效果是一样的。
注入方式
Union联合注入
union语句是一下可以查询两条语句的用法,需要注意的是前一句查询语句与后一句查询语句中查询的数量需要保持一直,否则会报错。
为了安全起见,本篇文章中所有的关于sql注入的测试都是在sqli-lab靶场进行的。下面演示下联合注入的基本常规操作与流程:
1 | ?id=1' order by 3%23 |
因为太简单,所有这里直接就放上最后一个步骤的图意思意思:
报错注入
在数据库查询时报错显示在前端,当报错输出与相关的函数一起使用的时候会产生奇妙的化学反应,产生的结果就是借助函数执行相关的语句并通过报错输出到前端。使用该类型的注入场景大多是在没有回显的情况下,下面列举一些使用的常见的函数:
extractvalue()
使用格式:extractvalue(x,x)。如:?id=1’) and (extractvalue(1,concat(0x7e,(select database()))))%23,这里举例sqli-lab的第三关:
分析源码,进行闭合后添加extractvalue()函数。
1 | ?id=1%27)%20and%20(extractvalue(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema="security"))))%23 |
后面就都一样了…….
updatexml()
使用格式:updatexml(x,x,x). ?id=1%27)%20and%20(updatexml(1,concat(0x7e,(select%20database())),1))%23 ,举例如下:
floor()
使用方法:与group by 一起配合使用。?id=1’) and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)%23,注意,这里的x,a为别名。
延时注入
通过sleep()函数与if()函数相互配合来设置延迟的响应时间进而去判断猜解出我们想要的信息。如下列:
?id=1%27)%20and%20if(ascii(substr(database(),1,1))>80,sleep(10),1)%23
布尔盲注
该方法返回值只有true与false两种状态,通过返回页面是正常状态还是异常状态来判断我们”猜“的东西是不是正确的。举例如下:
?id=1’) and ascii(substr(database(),1,1)>80)%23
二次注入
我对二次注入的理解是由于无法直接展开有效的sql注入,所有有了前期多次的半成品注入为最后一次注入行动做铺垫,这里选用的列子的是sqli-lab的第24关来演示,先看一下他的页面:
我们再来分析一他的创建新用户源码文件:
这里可以看见,对新用户的用户名和密码都进行转义,查询数据库不存在该用户后就直接插入到insert到数据中了,到这里都是一切正常的,问题处在修改用户修改密码的地方,我们再去看一下关于用户修改密码的源码文件:
这里可以看见对我们的输入也都进行转义,但出问题的地方不是这里,而是再第二个红框处,关于一个updata的语句,这条语句中的username是直接曲子数据库并且并没有进行检查,所有我们再第一次注册的是用户名使用:admin’#,然后再去修改密码时,会再这条更新语句处进行闭合,此时的语句就变成了如下所示:
1 | $sql = "UPDATE users SET PASSWORD='$pass' where username='admin'# and password='$curr_pass' "; |
很明显,这条语句造成的影响是,我们直接修改了用户名为:admin的账号。
约束攻击
这里关于约束攻击的描述我摘了一段来之安全客上文章的描述:假如注册时username参数在mysql中为字符串类型,并且有unique属性,设置了长度为VARCHAR(20)。则我们注册一个username为admin[20个空格]asd的用户名,则在mysql中首先会判断是否有重复,若无重复,则会截取前20个字符加入到数据库中,所以数据库存储的数据为admin[20个空格],而进行登录的时候,SQL语句会忽略空格,因此我们相当于覆写了admin账号。接下来我们还是以sqli-lab的24关为例:
这里注册一个用户:”admin aaa”,密码为:00000
查询后台改用胡只截取了admin和空格,二十个长度以外的都丢弃了。
使用密码00000来登录admin账号:
DNS注入
这里要用到的load_file()这个函数,该函数可以读取指定路径上的文件内容,同时还可以配合dns解析记录来外带数据库的相关信息。使用该函数的条件是需要mysql的配置文件mysql.ini中添加:secure_file_priv=,然后保存即可。这里列出几个该函数的使用模板:
1 | # 读取指定文件内容 |
HTTP头注入
跟数据库有交互的操作行为,我觉得都可以去测试一下是不是存在sql注入的漏洞,如http头注入,我们可以通过抓包,分析数据包的http头中的各个字段,比如Cookie,看看里面没有没有存在存储数据的行为,再次基础进行测试一番,说不定有意外的惊喜呢?
绕过方式
这里有的绕过方法就提一下思路,具体实施的细节请百度噢!
1 | # 大小写绕过 |
Fuzz绕过测试
Fuzz是安全测试的一种方法,面对waf无所适从的时候,可以使用Fuzz模糊测试来绕过waf,通过大量的字符,符号不断的尝试看响应结果来构造payload。