Java代审7-1:远程代码执行
0×01 产生原因
1、命令注入
2、代码注入
3、表达式注入
4、SSTI注入
0×02 命令注入
2.1 应用场景
2.2 漏洞原理
java 程序中执行系统命令的函数如下:
Runtime.exec
Process
ProcessBuilder.start
GroovyShell.evaluate
2.3 场景复现
public class RunTimeDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
Process exec = Runtime.getRuntime().exec(cmd);
InputStream is = exec.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
try {
exec.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
String s = null;
while ((s = reader.readLine()) != null) {
System.out.println(s);
out.write(s + "<br/>");
}
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
; 多个命令顺序执行,命令之间无任何逻辑关系
| 前面命令输出结果作为后面命令的输入内容
|| 逻辑或,当前面命令执行失败后,后面命令才会执行,否则后面命令不执行
& 前面命令执行后继续执行后面命令
&& 逻辑与,当前面命令执行成功后,后面命令才会执行,否则后面命令不执行
不存在命令注入的情况
//这种写法不存在命令注入
String ip = req.getParameter("ip");
Process exec = Runtime.getRuntime().exec("ping " + ip);
- 使用连接符导致参数报错
String cmd = "ping 127.0.0.1 ; curl http://127.0.0.1:800";
String cmd = "ping 127.0.0.1 | curl http://127.0.0.1:800";
String cmd = "ping 127.0.0.1 || curl http://127.0.0.1:800";
String cmd = "ping 127.0.0.1 & curl http://127.0.0.1:800";
String cmd = "ping 127.0.0.1 && curl http://127.0.0.1:800";
String cmd = "cmd /c ping 127.0.0.1&calc";
public class ProcessBuilderDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String output = null;
resp.setContentType("text/html;charset=utf-8");//解决页面编码问题
PrintWriter out = resp.getWriter();
// String cmd = req.getParameter("cmd");
// 模拟接收到的参数
String cmd ="cmd /c ping 127.0.0.1&calc";
String[] cmdSplit = cmd.split(" ");
ArrayList<String> cmdLines = new ArrayList<>();
for (int i = 0; i < cmdSplit.length; i++) {
cmdLines.add(cmdSplit[i]);
}
System.out.println(cmdLines.toString());
//使用ProcessBuilder创建命令执行对象
ProcessBuilder builder = new ProcessBuilder(cmdLines);
builder.redirectErrorStream(true);
Process process = builder.start();
//使用文件流读取输出结果
InputStream is = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((output = br.readLine()) != null) {
out.write(output + "</br>");
}
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
String cmdStart1 ="ping ";//后端写死
String cmdEnd1 = "127.0.0.1&whoami";//接收数据
String cmdStart2 ="cmd /c ping ";//后端写死
String cmdEnd2 = "127.0.0.1&&whoami";//接收数据
同时支持静态和动态类型;
支持运算符重载;
本地语法列表和关联数组;
对正则表达式的本地支持;
各种标记语言,如XML和HTML原生支持;
Groovy对于Java开发人员来说很简单,因为Java和Groovy的语法非常相似;
可以使用现有的Java库;
Groovy扩展了java.lang.Object;
<!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.7</version>
</dependency>
Runtime.getRuntime().exec("calc")和"whoami".execute() 本质相同
println "whoami".execute().text 还支持回显
import groovy.lang.GroovyShell;
import org.junit.Test;
public class MyTest {
@Test
public void test4() {
String cmd = "'calc'.execute()";
GroovyShell shell = new GroovyShell();
shell.evaluate(cmd);
}
}
String input="ping 127.0.0.1"; //用户输入需要执行的命令
String cmd = "println \""+input+"\".execute().text"; //获取执行命令的回显
在这里没有做编码处理,输出乱码,但是已经达到我们多命令注入的目的了。
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 奋力打开改革发展新天地 7991741
- 2 男子驾车冲撞小学生被判死缓 7960078
- 3 刘强东提前发年终奖 7811891
- 4 “冷资源”里的“热经济” 7757454
- 5 刘诗诗方辟谣离婚 7699476
- 6 微信可以线上送实体礼物了 7502254
- 7 王鹤棣先天松弛感圣体 7492729
- 8 #胡锡进说吴柳芳转型不易# 7349276
- 9 女子从体检“正常”到癌症仅半个月 7298361
- 10 肖战新片射雕英雄传郭靖造型曝光 7120826