2. Agenda
⢠Introduction
⢠Sql Injection
⢠Issue
⢠Remedies
⢠Inference Problem
⢠Issue
⢠Remedies
⢠Sql Stored procedures
⢠Defense in Depth Example
⢠Conclusion
3. Introduction
⢠Many applications, like web based applications and xml based web services
store persistent data in databases.
⢠Trusting that the user has given well-formed input data to your
application, when infact the user has not
⢠Misplaced trust
⢠Database input vulnerabilities (aka sql injection)
4. Web Application Vulnerabilities
Source
void ProcessRequest()
{
Sanitizer string s = GetUserInput("name");
âŚ
s = Validate(s);
âŚ
âŚ
ExecuteQuery(âselect âŚ" + s + ââŚâ);
}
Sink
Critical
Database
5. Sql Injection
⢠Many applications include code that looks something like
the following.
String sql = âselect * from client where name = ââ+name+âââ
The variable name is provided by the user
What if an attacker enters this: Blakeâ or 1=1 â
⢠select * from client where name = âBlakeâ or 1=1 â
⢠The comment operator â--â is supported by many
relational database servers, including Microsoft SQL
Server, IBM DB2, Oracle, PostgreSQL, and MySql.
6. Imagine that the database table
schema looks like this
C us tome r *
C ustome rID
La stNa me
F irstNa me
Middle Initia l
C us tome r C r e ditC ar d *
C ustome rID A ddre ss
C re ditC a rdID A pa rtme nt
C ity
Sta te
Posta lC ode
C ountry
C r e ditC ar d *
C re ditC a rdID
Ty pe
Numbe r
Ex pire s
When the attacker is happy that the SQL statement or statements are complete he
places a comment operator at the end to comment out any characters added by the
programmer.
7. SQL Injection
⢠Some database servers allow a client application to perform
more than one SQL statement at once.
⢠select * from table1 select * from table2
⢠SQL engines include support for data manipulation
constructs, such as the ability to create, delete (called drop),
an attacker could enter:
⢠Blakeâ drop table client --
8. Can you spot security flaws?
string Status = âNo";
string sqlstring = â"; Connecting as a super admin.
try {
SqlConnection sql= new SqlConnection(
@"data source=localhost;â + Sa is to SQL Server what SYSTEM is to
âuser id=sa;password=password;â); Windows NT and later.
sql.Open();
sqlstring="SELECT HasShippedâ +
â FROM detail WHERE ID=ââ + Id + ââ"; What if the connection fails to the
SqlCommand cmd = new SqlCommand(sqlstring,sql); database due to some network issue.
if ((int)cmd.ExecuteScalar() != 0)
Status = âYes";
A complete description of how the
} catch (SqlException se) { failure occurred is given to the attacker.
Status = sqlstring + â failednr";
foreach (SqlError e in se.Errors) {
Status += e.Message + ânr";
}
} catch (Exception e) {
Status = e.ToString();
}
9. Pseudoremedy:Quoting the Input
int age = ...; // age from user
string name = ...; // name from user
name = name.Replace(ââ","âââ);
SqlConnection sql= new SqlConnection(...);
sql.Open();
sqlstring=@"SELECT *â + â FROM client WHERE name= ââ + name + ââ or age=â + age;
SqlCommand cmd = new SqlCommand(sqlstring,sql);
Replacing single quotes with two single quotes. Statement becomes invalid SQL Statement.
⢠select * FROM client WHERE ID = âMichaelââ or 1=1 -- â or age=35
However, this does not deter our wily attacker; instead, he uses the age
field, which is not quoted, to attack the server. For example, age could be 35;
shutdown --.
declare @a char(20) select @a=0x73687574646f776e exec(@a)
This construct, when added to another SQL query, calls the shutdown command. The hexadecimal sequence is
the ASCII hex equivalent of the word shutdown.
10. Pseduremedy #2: Use Stored
Procedures
⢠A stored procedure is a procedure (like a subprogram in a regular
computing language) that is stored in the database
⢠Stored procedure: sp_GetName:
string name = ...; // name from user
SqlConnection sql= new SqlConnection(...);
sql.Open();
sqlstring=@"exec sp_GetName ââ + name + ââ";
SqlCommand cmd = new SqlCommand(sqlstring,sql);
⢠exec sp_GetName âBlakeâ or 1=1 -- â will fail
However performing data manipulation is perfectly valid.
⢠exec sp_GetName âBlakeâ insert into client values(1005, âMikeâ) -- â
Another Scariest example
CREATE PROCEDURE sp_MySProc @input varchar(128)
AS
exec(@input)
11. Remedy 1: Never Ever Connect as
sysadmin
⢠Delete (drop) any database or table in the system
⢠Delete any data in any table in the system
⢠Change any data in any table in the system
⢠Change any stored procedure, trigger, or rule
⢠Delete logs
⢠Add new database users to the system
⢠Call any administrative stored procedure or extended stored procedure.
⢠Support authenticated connections by using native operating system
authentication and authorization by setting Trusted_connection = true
⢠create a specific database account that has just the correct privileges to
read, write, and update the appropriate data in the database,and you should use
that to connect to the database.
⢠SQL Server includes extended stored procedures such as xp_cmdshell through
which an attacker can invoke shell commands.
⢠Oracle databases include utl_file, which allows an attacker to read from and
write to the file system
12. Remedy #2: Building SQL Statements Securely
Function IsValidUserAndPwd(strName, strPwd)
â Note I am using a trusted connection to SQL Server.
⢠Use parameterized commands. â Never use uid=sa;pwd=
strConn = âProvider=sqloledb;â + _
⢠SELECT count(*) FROM client âServer=server-sql;â + _
âdatabase=client;â + _
WHERE name=? AND pwd=? âtrusted_connection=yes"
Set cn = CreateObject(âADODB.Connectionâ)
cn.Open strConn
Set cmd = CreateObject(âADODB.Commandâ)
cmd.ActiveConnection = cn
cmd.CommandText = _
âselect count(*) from client where name=? and pwd=?"
cmd.CommandType = 1 â 1 means adCmdText
cmd.Prepared = true
â Explanation of numeric parameters:
â data type is 200, varchar string;
â direction is 1, input parameter only;
â size of data is 32 chars max.
Set parm1 = cmd.CreateParameter(âname", 200, 1, 32, ââ)
cmd.Parameters.Append parm1
parm1.Value = strName
Set parm2 = cmd.CreateParameter(âpwd", 200, 1, 32, ââ)
cmd.Parameters.Append parm2
parm2.Value = strPwd
Set rs = cmd.Execute
IsValidUserAndPwd = false
If rs(0).value = 1 Then IsValidUserAndPwd = true
rs.Close
cn.Close
End Function
13. Building SQL Stored Procedures
Securely
⢠Use quotename function
select top 3 name from mytable would
become
select top 3 [name] from [mytable]
if you quote name and mytable .
declare @a varchar(20)
set @a=0x74735D27
select @a
set @a=quotename(@a)
select @a
set @a=âts]âââ
select @a
set @a=quotename(@a)
select @a
Use sp_executesql to execute sql statements build dynamically.
-- Test the code with these variables
declare @name varchar(64)
set @name = NâWhiteâ
-- Do the work
exec sp_executesql
Nâselect au_id from pubs.dbo.authors where au_lname=@lnameâ,
Nâ@lname varchar(64)â,
@lname = @name
14. Inference Problem â 1
⢠The inference problem is a way to infer or derive
sensitive data from nonâsensitive data.
⢠Sum: An attack by sum tries to infer a value from
reported sum. Often helps us determine a negative
result.
⢠This report reveals that no female living in Grey is receiving
financial aid
15. Inference problem 2
⢠Count: count + sum ď average; average + count ď sum
⢠This report reveals that two males in Holmes and West are
receiving financial aid in the amount of $5000 and $4000,
respectively.
⢠Holmes ď Adams
⢠West ď Grof
17. Remedies: Statistical Inference
Controls Attacks
⢠Controls are applied to queries
⢠Difficult to determine if query discloses sensitive data
⢠Controls are applied to individual items within the database
(security vs. precision)
⢠Suppression: sensitive data values are not provided; query is
rejected without response
⢠Many results suppressed; precision high
⢠Concealing: answer provided is close to by not exactly the actual
value
⢠More results provided; precision low
18. Remedies: Limited Response
Suppression
⢠The nâitem kâpercent rule eliminates certain lowâfrequency
elements from being displayed
⢠When one cell is suppressed in a table with totals for rows and
columns, must suppress at least one additional cell on the row
and one on the column to provide some confusion.
19. Other Suppression and
Concealing
⢠Combine rows or columns to protect sensitive values
⢠Take a random sample (sample must be large enough to be valid)
⢠Same sample set would be repeated for equivalent queries
⢠Query analysis
⢠Query and its implications are analyzed
⢠Can be difficult
⢠Maintain query history for each user
⢠⌠no perfect solution to inference problem
⢠⌠recognizing the problem leads to being defensive
20. Defense in Depth Example
//
// SafeQuery
//
//Add shipping ID parameter.
Using System; string str="sp_GetName";
Using System.Data; cmd = new SqlCommand(str,sqlConn);
Using System.Data.SqlTypes; cmd.CommandType = CommandType.StoredProcedure;
Using System.Data.SqlClient; cmd.Parameters.Add(â@ID",Convert.ToInt64(Id));
Using System.Security.Principal;
Using System.Security.Permissions; cmd.Connection.Open();
Using System.Text.RegularExpressions; Status = cmd.ExecuteScalar().ToString();
Using System.Threading;
Using System.Web; } catch (Exception e) {
Using Microsoft.Win32; if (HttpContext.Current.Request.UserHostAddress == â127.0.0.1â)
... Status = e.ToString();
else
[SqlClientPermissionAttribute(SecurityAction.PermitOnly, Status = âError Processing Request";
AllowBlankPassword=false)] } finally {
[RegistryPermissionAttribute(SecurityAction.PermitOnly, //Shut down connection--even on failure.
Read=@"HKEY_LOCAL_MACHINESOFTWAREClientâ)] if (cmd != null)
static string GetName(string Id) cmd.Connection.Close();
{ }
return Status;
SqlCommand cmd = null; }
string Status = âName Unknown"; //Get connection string.
(continued) internal static string ConnectionString {
get {
try { return (string)Registry
//Check for valid shipping ID. .LocalMachine
Regex r = new Regex(@"^d{4,10}$â); .OpenSubKey(@"SOFTWAREClientâ)
if (!r.Match(Id).Success) .GetValue(âConnectionStringâ);
throw new Exception(âInvalid IDâ); }
}
//Get connection string from registry.
SqlConnection sqlConn= new SqlConnection(ConnectionString);
21. Defense in Depth Example
⢠Blank passwords are never allowed when connecting to the database.
⢠Read only one specific key from the registry; it cannot be made to
perform other registry operations.
⢠The code is hard-core about valid input: 4â10 digits only. Anything else
is bad.
⢠The database connection string is in the registry, not in the code and not
in the Web service file space, such as a configuration file.
⢠The code uses a stored procedure, mainly to hide the application logic in
case the code is compromised.
⢠connection is not using sa. Rather, itâs using a least-privilege account
that has query and execute permissions in the appropriate tables.
⢠use parameters, not string concatenation, to build the query.
⢠The code forces the input into a 64-bit integer.
⢠On error, the attacker is told nothing, other than that a failure occurred.
⢠The connection to the database is always shut down regardless of
whether the code fails.
22. Conclusion
⢠Do not trust the userâs input!
⢠Be strict about what represents valid input and reject
everything else. Regular expressions are your friend.
⢠Use parameterized queriesânot string concatenationâto
build queries.
⢠Do not divulge too much information to the attacker.
⢠Connect to the database server by using a least-privilege
account, not the sysadmin account.