Self-Defending Databases
Alexander Kornbrust,
Red-Database-Security GmbH
Agenda
¡ Introduction
¡ Root Cause
¡ Anatomy of an attack
¡ Detection of an attack
¡ Countermeasures
¡ How to implement
¡ Discussion
Introduction
This presentation shows how databases can defend themselves against
SQL Injection attacks without human interaction.
Web applications/services are permanently attacked from the internet
(successful/unsuccessful). A successful attack often leads to data loss
(e.g. data is posted on websites like pastebin.com ).
The majority of attacker are using tools to attack web applications and
to download data that’s why human reaction on these events is
normally to slow.
Introduction
Monitoring 30 web applications: (Imperva Trend Report #4, Sep 2011)
¡ on average 71 SQL injection attempts per hour
¡ 800-1300 injection attempts at peak times
¡ Use of highly automated SQL injection tools, e.g. sqlmap, Havij,...
http://www.imperva.com/download.asp?id=352
https://www.hashdays.ch/slides/2011/bockermann_hashdays11.pdf (
Hashdays 2011 – Protecting
Databases with Trees
The presentation “A syntax-based approach to detect SQL injections”
from Christian Bockermann showed how to use the parse tree to detect
SQL Injection attacks.
This approach is smart but complex (SQL Parser, Training data, …).
Additionally it does not answer the problem what to in case of an SQL
Injection.
https://www.hashdays.ch/slides/2011/bockermann_hashdays11.pdf
Root Cause
Problem:
Web applications are often vulnerable against SQL Injection
Solution:
Fix all vulnerable web applications and allow only the
deployment of secure (after pentest) applications
Is this really realistic in a
(large) organization?
No !
¡ There is no secure code
¡ Majority of applications are not pentested
¡ Applications are longer used than expected (sometimes 10+ years)
¡ Application patches are difficult to get/patch or not available
Anatomy of an SQL Injection
Web Attack
1. Use a tool (e.g. Havij, Netsparker, Matrixay,
Pangolin, SQLMap, …) or google to find a SQL
Injection vulnerability by crawling the entire
website
2. Select the tables (data) in the tool
3. Download the data via the tool
1. Find a SQL Injection
Vulnerability
Google Hacking
2. Select the data
3. Download the data
And the data is gone ...
(in often less than 2 minutes)
Potential Reaction for SQL Inj.
Attacks
Solution:
Within 2 minutes after the attack started, the Manager on
Duty is receiving an alert and automatically stops the attack
by shutting down the service
Is this really realistic in a
(large) organization?
No !
¡ Time for a human reaction is too short
¡ Several companies do not have a Security information and event Management
( SIEM ) and Security Operation Center (SOC) in place to forward these kind of alert,
¡ Even with a SIEM system 2 minutes are a challenge for most organizations
¡ Side effects of a stopping a system/service is not documented in most companies
¡ A manager on duty would normally not stop a system
We don’t live in a perfect
world that’s why we need a
different real-world
approach against SQL
Injection attacks
Approach
1. The system itself has to detect the hacking attempt
2. Appropriate counter measures have to be taken
Detection
How and where can we detect a SQL Injection hacking attempt?
¡ Web Application Firewall (WAF/IDS)
¡ Can block some of the attacks by filtering the input
¡ Webserver
¡ Can block some of the attacks by filtering the input (mod_security)
¡ Application
¡ Not without changing the application itself (which is difficult)
¡ Database
¡ Yes, by detecting SQL errors
Detection
Out-of-the-box Databases like Oracle or Microsoft SQL Server are able
to detect SQL specific error messages and can run (custom) code
(=countermeasure) after the detection.
MySQL could use this technique via a MySQL proxy.
These specific database errors only occur if a vulnerability exists and
this vulnerability was triggered by a specific string (e.g. “or 1=1--”)
False positives are rare. A false positive could occur if a developers are
deploying applications with incorrect SQL statement (e.g. missing
single quote).
Implementation
The implementation of this detection has to be done in different ways
depending from the underlying database:
Oracle:
¡ Database Errror Trigger
Microsoft SQL Server:
¡ Event Notification
MySQL:
¡ MySQL Proxy or MySQL Audit Plugin*
* http://dev.mysql.com/doc/refman/5.5/en/writing-audit-plugins.html
Detection of SQL Injection
attacks via error messages
• Depending from the used attack method (UNION, extend query,
create error messages to retrieve data, …) a specific error will be
created
e.g.
ORA-01789: query block has incorrect number of result columns
• Or
Microsoft OLE DB Provider for ODBC Drivers error
'80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax
error converting the nvarchar value ’mypassword' to a column of
data type int. /Administrator/login.asp, line 27
Typical SQL Injection Attack I
Original SQL command
select custname, custid, custorder from customer;
SQL command extended by an attacker
select custname, custid, custorder from customer
union
select username, null, password from dba_users;
Typical SQL Injection Attack II
Typical SQL Injection Attack III
Typical SQL Injection Attack IV
Typical SQL Injection Attack V
Injected:
Union null,username from all_users--
Error message:
ERROR at line 1:
ORA-01789: query block has incorrect number of result
columns
è Attacker (or tool) is adding NULLs until a proper SQL
statement was created and executed
Next attempt:
Union null,null,username from all_users—
Typical SQL Injection Attack VI
SQL Injection Error Codes Oracle - I
Error code
Error Message
Typical Command
ORA-00900
invalid SQL statement
ORA-00906
missing left parenthesis
ORA-00907
missing right parenthesis
ORA-00911
invalid character
e.g. PHP MAGIC_QUOTES_GPC
activated and attempt to
inject a single quote
ORA-00917
missing comma
ORA-00920
invalid relational operator
ORA-00923
FROM keyword not found where expected
ORA-00933
SQL command not properly terminated
ORA-00970
missing WITH keyword
ORA-01031
insufficient privileges
Attempted privilege escalation
ORA-01476
divisor is equal to zero
Blind SQL Injection attempt
(e.g. sqlmap)
ORA-01719
outer join operator not allowed in operand
of OR or IN
ORA-01722
invalid number
Enumeration with rownum and
current rownum does not exist
SQL Injection Error Codes Oracle - II
Fehlernr
Fehlermeldung
Auslöser
ORA-01742
comment not properly terminated
inline comment, e.g
optimizer hint is not properly
terminated
ORA-01756
quoted not properly terminated
single quote not properly
terminated
ORA-01789
query block has incorrect number of Attempt to use UNION
result columns
SELECT
ORA-01790
expression must have same datatype Attempt to use UNION
as corresponding
SELECT
ORA-24247
network access denied by access Oracle ACL has blocked
control list
the usage of UTL_INADDR
(or similar)
ORA-29257
Host %S unknown
Attempted SQL Injection
via utl_inaddr
ORA-29540
Class does not exist
Attempted utl_inaddr
attempt but Java is not
installed
ORA-31011
XML parsing failed
SQL Injection attempt via
xmltype
ORA-19202
Error occurred in XML processing
SQL Injection via
extractvalue
SQL Injection Error Codes MSSQL
Error Message
Typical Command
Unclosed quotation mark before the character Usage of single quotes
string ''
Syntax error converting the varchar value 'test' to a Usage of --
column of data type int.
Column
'[COLUMN
NAME]'
is
invalid
in
the
select
list
http://[site]/page.asp?id=1
having
1=1-‐-‐
because
it
is
not
contained
in
an
aggregate
function
and
there
is
no
GROUP
BY
clause.
Syntax
error
converting
the
nvarchar
value
'[DB
http://[site]/page.asp?id=1
or
USER]'
to
a
column
of
data
type
int.
1=convert(int,(USER))-‐-‐
http://www.evilsql.com/main/page2.php
React on errors
• The system could react on the errors caused by SQL Injection attempts
• Detection only / Audit the event
• Send an email to the manager-on-duty/DBA/Security Department
• Lock the database account
• Terminate this session or terminate all sessions
• To minimize the impact, different database accounts should be used
for different applications (e.g. Internet, Intranet, Android, iOS, ..).
• If the application is blocked from the internet, intranet users can still
work with the application.
• Only errors caused by the application server should create such a
reaction (i.e. ORA-01756 from SQL*Plus, TOAD or SQL Management
Studio will be ignored)
Additional options to react
• After the account was locked the user can‘t use the webapp
• Send an email to the operating and/or Manager on Duty
• Analyze error ( 'or 1=1 oder O‘Leary)
• Unlock account in case of false positive
• In case of a real alert try to identify the type of attacker
(Amateur, Pro, Skript-Kiddie with tool, …)
• Option to lock ip ranges (lock only people outside of hungary)
• Fix the software bug and/or search a workaround.
Oracle Error Trigger
- Sample code
CREATE OR REPLACE TRIGGER after_error
AFTER SERVERERROR ON DATABASE
DECLARE
sql_text ORA_NAME_LIST_T;
v_stmt CLOB; -- SQL statement causing the problem
n NUMBER; -- number of junks for constructing the sql statement causing the
error
v_program VARCHAR2(64);
v_serial number;
v_sid number;
BEGIN
-- Version 1.00
select program,serial#,sid into v_program,v_serial,v_sid from v$session where
sid=sys_context('USERENV', 'SID');
-- construct the sql text
n := ora_sql_txt(sql_text);
--
IF n >= 1
THEN
FOR i IN 1..n LOOP
v_stmt := v_stmt || sql_text(i);
END LOOP;
END IF;
--
FOR n IN 1..ora_server_error_depth LOOP
IF (lower(v_program) = 'iis.exe') -- add your own application server
and (ora_server_error(n) in
('942','900','906','907','911','917','920','923','933','970','1031','1476','1719','1722','1742','1756','17
89','1790','19202','24247','29257','29540','31011'))
THEN
-- Potential attack was detected
-- 1. Monitor the attack
-- 2. Send an email to the responsible person (DBA/MoD)
-- send_email (e.g. via utl_smtp )
-- 3. Lock database user used by the webapp
execute immediate ('ALTER USER /* Error_Trigger */ "'|
sys_context('USERENV','SESSION_USER')||'" account lock');
-- 4. Terminate Session
execute immediate ('ALTER SYSTEM /* Error_Trigger */ KILL SESSION '''||v_sid||','||
v_serial||''' account lock');
alter system kill session 'session-id,session-serial'
-- 5. Other countermeasures
END IF;
END LOOP;
--
END after_error;
/
SQL Server
Concept SQL Server
• Event notifications are a special kind of database object that
send information about server and database events to a Service
Broker service.
• Create events for typical SQL injection errors
http://weblogs.sqlteam.com/mladenp/archive/2008/07/18/Immediate-deadlock-notifications-without-changing-existing-code.aspx
http://msdn.microsoft.com/en-us/library/ms189453.aspx
MySQL
(all credits go to Xavier Mertens)
http://blog.rootshell.be/2012/11/01/mysql-attacks-self-detection/
Concept MySQL
Concept MySQL
• Create an UDF to write errors in a log file.
• A LUA script will rewrite the query by appending the “SHOW
WARNINGS” statement + some variables at the end of the query.
• Then the query results of the modified query will be read by the
LUA scripts and written to a log-file
• It is also possible to lock the MySQL user account (similar to the
other databases)
Countermeasures after
detecting an attack
Countermeasures after detection I
Monitor the attempt and send an email to the security officer
Pro:
¡ Small footprint
¡ No side effect on the application
Cons:
¡ Fast response needed
¡ What happens during the night, vacation, …
Countermeasures after detection II
Lock the database account and kill all already running processes
Pro:
¡ Attack is immediately stopped
¡ Do data is lost
Cons:
¡ Side effect on the application (Denial-of-Service)
¡ Potential false positive
Countermeasures after detection III
Get the IP address from the web application server and start a
denial-of-service against the IP where the attack was coming from
Pro:
¡ Database strikes back ;-)
Cons:
¡ Is this legal?
What do you prefer?
Service not available
or
Data is lost/published?
What happens after lockout?
Manager on Duty can decide if the database account should be
re-enabled / unlock.
This is normally an easier decision instead of stopping a service to
stop an on-going attack?
Potential false positives
If a web application is vulnerable against SQL Injection attacks, an
“accidental” string like “O’Leary” can trigger the account lockout.
In this case the string was not part of an attack. In such a case it could
be an option to exclude the string from the detection and re-enable
the service again.
The vulnerability should be fixed as soon as possible.
Or
Developer has deployed wrong SQL code (e.g. Single Quote is missing)
SQL Injection Errors from Web Application
Scanner
If a web application is vulnerable against SQL Injection attacks, and
a web application scanner is performing a scan we know that we
are under attack.
How can we detect that a webapp scanner was causing the error?
SQL Injection Errors from Web Application
Scanner
Vulnerable URL:
php3.php?ename=test
Webapp Scanner is trying to inject patterns and analyzes the result
php3.php?ename=' and 1=0 union select 1,password from dba_users
where username='SYSTEM’--
ERROR:
ORA-01789 - query block has incorrect number of result columns
SQL Statement:
Select * from emp where ename=‘’ and 1=0 union select 1,password from
dba_users where username='SYSTEM’--
è Acunetix was used
Acunetix – Forensic Traces
Test strings (partial)
|| (select username from dual) --
' union select username,password from
dba_users--
'union select user, sysdate from dual
--
and 1=0 union select 1,2 from dual--
and 1=1 Union select null,banner from v
$version--!
SQL Injection Errors from Web Application
Scanner
Vulnerable URL:
php1.php?id=7900
Webapp Scanner is trying to inject patterns and analyzes the result
php1.php?id=' OR 'ns'='ns
ERROR:
ORA-00933: SQL command not properly ended
SQL Statement:
Select * from emp where id=' OR 'ns'='ns
è Netsparker (ns) was used
Netsparker – Forensic Traces
Test strings (partial)
OR 17-7=10
+CHAR(95)+CHAR(33)+CHAR(64)
' OR 'ns'='ns
OR 1=1
/**/AND/**/1=/**/
CHAR(95)+CHAR(33)+CHAR(64)+SUBSTRING(CA
ST((SELECT/**/@@version)/**/AS/**/
varchar(3000)),
0,343)+CHAR(95)+CHAR(33)+CHAR(64)
Matrixay – Forensic Traces
Test strings (partial)
AnD 1=1
AnD AsC(1)<65535
AnD user<Chr(0)
AnD (SeLEcT CoUNt(TaBLe_NaME) FrOM
user_tables)>0
AnD AsCIi(DaTAbAsE())=0!
HP Webinspect – Forensic Traces
Test strings (partial)
value' OR 5=5 OR 's'='0
value' AND 5=5 OR 's'='0
value' OR 5=0 OR 's'='0
value' AND 5=0 OR 's'='0
0+value
value AND 5=5
value AND 5=0
value OR 5=5 OR 4=0
value OR 5=0 OR 4=0
Pangolin – Forensic Traces
Test strings (partial)
union all select null from dual-- and
1=1
union all select null,null from dual--
and 1=1
and (select length(table_name) from
(select rownum r,table_name from
(select rownum r,table_name from
user_tables where rownum<=1 order by 1
desc)
SQL Injection Errors from Web Application
Scanner
A stored procedure in the database could be used to identify the
common SQL Injection tools and block the access.
This stored procedure is called inside the trigger/event notification.
Improve the concept I
¡ The application could use dedicated connections for dedicated
services (e.g. internal users and external users are using a different
connection or special connections for IOS and Android Apps). A
lockout of the external users does not affect the internal users
¡ Block only IP’s or IP ranges from specific blocks/regions/countries
(e.g. if majority of customers is coming from CH, block requests
from the outside of CH)
Improve the concept II
¡ The database mechanism to detect attacks could communicate
with the webserver to block specific IPs already at the webserver
level instead of blocking the entire account
è Depends how much time and effort is done for the
implementation
Improve the concept III
¡ Use different weights for the decision what to do
¡ Error comes from a TOR network +10
¡ Error comes from the intranet +4
¡ Error comes from an uncommon country (e.g. Turkemnistan) +7
¡ Injected string contains a -- +10
¡ Know attack string from webapp scanner +20
¡ Single quote comes after D, O +1 (Palm D’or, O’Connor) +1
¡ Single quote comes after a nonD/non-O +3
¡ …
¡ Add all weights
¡ If a certain weight is reached lock the user
Other ways to detect an
SQL Injection attack
Fake Data (Honey Data)
¡ Using fake data could help to identify attacks which are not triggered by
error messages (e.g. if attacker uses a known exploit for standard
software (e.g. Wordpress, …))
¡ Fake data (Honey data) is data (e.g. Passwords, Credit card numbers,
…) in tables which is never used by the application. If someone from the
web application server is accessing this kind of data this is often part of
the data discovery process of the attacker.
Fake-Data (Honey-Data)
• Creation a table or tables containing unused data with juicy
names (e.g. PASSWORD, CREDITCARD, SALARY). Such interesting
data is often the target of attackers.
• During the attack, attackers are often accessing the view
ALL_TAB_COLUMNS (Oracle) or INFORMATION_SCHEMA.COLUMNS
(MSSQL) to get the column names of interesting data
• Attackers are normally downloading the data of interesting tables
found via the column name in further attacks.
• You could monitor such an access and could react (send email,
lock user, …)
• Oracle can implement this monitoring via Virtual Private Database
(VPD)
Fake-Data (Honey-Data)
-- Create Honeytable
create table app.userdata (username varchar2(30), password varchar2(30));
-- Fill Honeytable with data
insert into app.userdata values ('WEBUSER','WEBUSER01');
insert into app.userdata values ('WEBADM','ADMADM01');
insert into app.userdata values ('WEBREAD','READUSER01');
-- create predicate function
create or replace function perfcheck (pv_schema in varchar2, pv_object in
varchar2)
return varchar2 as
begin
dbms_output.put_line(‘Send email to the security team or lock the database user...');
-- return always true. Attacker will see all results
return '1=1';
end;
/
-- now we activate VPD for this table
exec dbms_rls.add_policy(object_schema => ‘APP', object_name => ‘USERDATA',
policy_name => 'PERFCHECK', policy_function => 'PERFCHECK');
VPD is free but requires Oracle Enterprise Eidition
Fake Functions
¡ Developers are typically using obvious function names.
¡ A common function name for encrypting/decrypting data is
encrypt()/decrypt().
¡ If an attacker finds a encrypted password column and a function
called decrypt, he will probably use the decrypt function:
Select decrypt(password) from app.appusers;
¡ Instead of decrypting the the password, this function is sending an
email to the security officer.
Summary
¡ Self-Defending databases can be a cheap and fast step to
protect databases.
¡ Implementation is transparent. No need to change the
application (but it could be useful)
¡ Can also be used during pentests to monitor if SQL Errors were
triggered by Pentesters
¡ Data loss can be prevented
¡ Dilemma for the management:
Stop the service or stop the data loss
Q & A?
Thanks
¡ Contact:
Red-Database-Security GmbH
Bliesstr. 16
D-.66538 Neunkirchen
Germany