43
Understanding SQL BY: JOHN PATRICK LITA INFORMATION SECURITY CONSULTANT – GLOBE TELECOM

Understanding sql

Embed Size (px)

Citation preview

Page 1: Understanding sql

Understanding SQLBY: JOHN PATRICK LITAINFORMATION SECURITY CONSULTANT – GLOBE TELECOM

Page 2: Understanding sql

ONLINE BANK

Email Address

PasswordLog in

Our website is secure, almost never get hacked

Page 3: Understanding sql

ONLINE BANK

[email protected]

passwordLog in

Our website is secure, almost never get hacked

Lets assume the attacker trying to guess what is the password of tcon

user

Unknown username and password

An error message prompted

Page 4: Understanding sql

ONLINE BANK

[email protected]

password’Log in

Our website is secure, almost never get hacked

By adding a single quote (‘) at the end of the password, lets see the behavior of

the application

An unexpected Error occuredAn error message

prompted

The logs show aSQL Syntax error.This indicates that The quote characterMessed something upIn an unexpected way

Page 5: Understanding sql

SELECT *FROM usersWHERE email = ‘?’AND pass = ‘?’ LIMIT 1

This is what the application code looks

like behind the scenes. Let’s see how

the SQL code gets built as you enter your login details

Page 6: Understanding sql

ONLINE BANK

[email protected]

password’Log in

Our website is secure, almost never get hackedAn unexpected Error occurred

"'password'' limit 1" LINE 1: ...ers where email = ‘[email protected]' and

password = 'password'... ^ : select * from users where email =

[email protected]' and password = 'password'' limit 1.Unable to login this

user due to unexpected error.

Page 7: Understanding sql

Unexpected Error

SELECT *FROM usersWHERE email = ‘[email protected]’AND pass = ‘password’’ LIMIT 1This is what the

application code looks like behind the

scenes. Let’s see how the SQL code gets built as you enter your login details

Page 8: Understanding sql

Authentication Bypass 1

ONLINE BANK

Email Address

PasswordLog in

Our website is secure, almost never get hacked

Enter the following credentials and click “Log In”:

Email:

[email protected]

Password:

‘ or 1=1--

Page 9: Understanding sql

Authentication Bypass 1

ONLINE BANK

[email protected]

‘ or 1=1--Log in

Our website is secure, almost never get hacked

Rendering login page.Checking supplied authentication details for [email protected] user in database.Authentication details confirmed, establishing session for this user.

Page 10: Understanding sql

Authentication Bypass 1

ONLINE BANKBank Accounts

Account Available Balance Present BalanceChecking PHP 80,260.56 PHP 80,260.56Savings PHP 95,895.96 PHP 95.895.96

Transfer Funds!

Page 11: Understanding sql

Authentication Bypass 1

SELECT *FROM usersWHERE email = ‘[email protected]’AND pass = ‘1 or 1=1--’ LIMIT 1

The - - characters you entered cause the database to ignore the rest of the SQL

statement, allowing you to be authenticated without having to supply the real password

Page 12: Understanding sql

Code walkthroughHACKTHENORTH.ORG

Page 13: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Page 14: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

To validate user credentials, the request.getParamenter()

method is first called to extract tcon’s email (from HTTP request parameter)

which is assigned to the email variable

Page 15: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Similarly, the request.getParameter()

method is called to extract tcon’s password value and

assigned to password variable

Page 16: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

The string variable sql is then declared which represents the SQL query used to authenticate tcon’s

credentials.

Note, the tcon’s email and password value are concatenated to build the

final query

Page 17: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

The SQL query in defined in sql string variable is then executed by invoking the executeQuery method. This method executes our query against the backend SQL server and returns a result as

ResultSet object which is on result.next through the if/else block

Finally, should tcon’s credentials match the loggedIn variable is set to true and tcon is redirected to its profile page.

Page 18: Understanding sql

Simplify the Code

Page 19: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Page 20: Understanding sql

Code walkthrough//string email = request.getParameter("Email");//String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

//Connection connection = pool.getConnection();//Statement statement = connection.createStatement();//ResultSet result = statement.executeQuery(sql);

//if (result.next()) {//LoggedIn = true;// #Successfully logged in and redirect to user profile page//} else {// #Authentication failure - Redirect to login page//}

Now that we have simplified our authentication logic code, lets analyze the SQL query generated by Bank to validate tcon’s

authentication credentials

Page 21: Understanding sql

Understanding Injection

Step 1: Enter the password [email protected] and watch the code widow. Notice how the single quote (‘) you appended is interpreted by the SQL server as a string delimiter.

However, when the query is processed, the last quote does not have a closing/matching (‘) character, which cause a SQL Syntax Error, resulting in the HTTP 500 Internal server Error

Step 2: Now try logging with a password followed by two single quotes e.g. password’’ Interestingly the application does nor error in this case

Page 22: Understanding sql

Action:1

ONLINE BANK

Email Address

PasswordLog in

Our website is secure, almost never get hacked

Page 23: Understanding sql

Action:1

ONLINE BANK

[email protected]

password’Log in

Our website is secure, almost never get hacked

Page 24: Understanding sql

Action:1

ONLINE BANK

Our website is secure, almost never get hacked

Page 25: Understanding sql

Action:1

ONLINE BANK

Our website is secure, almost never get hacked

500 Internal Server Error.

The server encounter an internal error or misconfiguration and was unable to complete your

request. Please contact your handsome administrator and inform them of the time the error occurred, and anything might have done that may have caused the

error.Also by them a coffee or burger so that they will fix

your problem

Page 26: Understanding sql

Action:2

ONLINE BANK

[email protected]

password’’Log in

Our website is secure, almost never get hacked

Page 27: Understanding sql

Action:2

ONLINE BANK

Email

passwordLog in

Our website is secure, almost never get hacked

ERROR: Invalid username and password

Page 28: Understanding sql

Bypassing Authentication

At this point we know that injecting characters interpreted by the database server is known as SQL injection

How ever, it’s not just (‘) characters that can be injected, entire strings can be injected, entire strings can be injected. What if this could be used to alter the purpose of the SQL Statement Entirely?

Page 29: Understanding sql

Bypassing Authentication

ONLINE BANK

[email protected]

Password ‘ 1 or 1=1)#

Log in

Our website is secure, almost never get hacked

Note in MySQL the (#) character is used for code comments. Keep an eye on the code, everything to the right of the (#) character is commented our, including the extra (‘) and ) character.

Note: the provided SQL payload is the one must use

Page 30: Understanding sql

Bypassing Authentication

ONLINE BANK

Our website is secure, almost never get hacked

Page 31: Understanding sql

Bypassing Authentication

ONLINE BANKBank Accounts

Account Available Balance Present BalanceChecking PHP 80,260.56 PHP 80,260.56Savings PHP 95,895.96 PHP 95.895.96

Transfer Funds!

Page 32: Understanding sql

Authentication was bypass, but why?

The credentials we provide on the login resulted in the following SQL statement:

SELECT *WHERE (email = ‘[email protected]’)AND password = ‘ ‘ OR 1=1)#

Because the statement is both syntactically valid and OR 1=1 always return true, the authentication mechanism was bypassed. Let’s now analyze the Vulnerability from a code perspective

Page 33: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

To quickly recap, the request.getParameter() method is first called to

extract tcon’s username and password values which are assigned to the email and

password variable

Page 34: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

The string variable sql is then declared, which represents the SQL query used to

authenticate tcon’s credentials

Page 35: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

String sql = "select * from users where (email='" + email +"' and password='" + password +"')";

Connection connection = pool.getConnection();Statement statement = connection.createStatement();ResultSet result = statement.executeQuery(sql);

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Notice that tcon’s email and password input (retrieved using the request.getParameter() method) are concatenated within the variabl sql , without any input validation checks.

Page 36: Understanding sql

Input Validation

Because there is no input validation (i.e. no checking of legal characters, minimum/maximum string lengths, or removal of “malicious” characters) TCON has the ability to inject raw SQL syntax within the username and password input fields to alter the meaning of the underlying SQL query responsible for authentication, resulting in a bypass of the application’s authentication mechanism

A SQL Injection Attack!

Page 37: Understanding sql

RemediationHACKTHENORTH.ORG

Page 38: Understanding sql

Remediation

Prepared Statements (A.K.A parameterized queries) are the best mechanism for preventing SQL injection attacks

Prepared statements are used to abstract SQL statement syntax from input parameters. Statement templates are first defined at the application layer, and the parameters are then passed to them

In java this can be achieved using PreparedStatement class for sending SQL statements to the backend database

Aside from a better security posture against SQL injection attacks, prepared statements offer improved code quality from a legibility and maintainability perspective due to separation of SQL logic from inputs

Page 39: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

//String sql = "select * from users where (email='" + email +"' and password='" + password +"')";String sql = “select * from users where email = ? and password = ?”;

Connection connection = pool.getConnection();//Statement statement = connection.createStatement();PreparedStatement preparedStatement = connection.prepareStatement(sql);

//ResultSet result = statement.executeQuery(sql);

preparedStatement.setString(1, email);preparedStatement.setString(2, password);

ResultSet result = preparedStatement.executeQuery();

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

In our modified code example, we first declared the authentication query string and assign it to the sql string variable. Notice that the email and password variable have now been replace with (?) symbol which act as a place holder for java’s PreparedStatement class.

Page 40: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

//String sql = "select * from users where (email='" + email +"' and password='" + password +"')";String sql = “select * from users where email = ? and password = ?”;

Connection connection = pool.getConnection();//Statement statement = connection.createStatement();PreparedStatement preparedStatement = connection.prepareStatement(sql);

//ResultSet result = statement.executeQuery(sql);

preparedStatement.setString(1, email);preparedStatement.setString(2, password);

ResultSet result = preparedStatement.executeQuery();

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

The sql string variable is then passed as an argument to the preparedStatement() method, which precompiles the SQL query and creates a PreparedStatement object for sending parameteized SQL statements to the back end SQL Server

Page 41: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

//String sql = "select * from users where (email='" + email +"' and password='" + password +"')";String sql = “select * from users where email = ? and password = ?”;

Connection connection = pool.getConnection();//Statement statement = connection.createStatement();PreparedStatement preparedStatement = connection.prepareStatement(sql);

//ResultSet result = statement.executeQuery(sql);

preparedStatement.setString(1, email);preparedStatement.setString(2, password);

ResultSet result = preparedStatement.executeQuery();

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Similarly, the setString() method is then called to pass the password parameter value to our prepared statement.

Page 42: Understanding sql

Code walkthroughstring email = request.getParameter("Email");String password = request.getParameter("password");

//String sql = "select * from users where (email='" + email +"' and password='" + password +"')";String sql = “select * from users where email = ? and password = ?”;

Connection connection = pool.getConnection();//Statement statement = connection.createStatement();PreparedStatement preparedStatement = connection.prepareStatement(sql);

//ResultSet result = statement.executeQuery(sql);

preparedStatement.setString(1, email);preparedStatement.setString(2, password);

ResultSet result = preparedStatement.executeQuery();

if (result.next()) {LoggedIn = true;

#Successfully logged in and redirect to user profile page} else {

#Authentication failure - Redirect to login page}

Finally, we execute our authentication query by invoking the preparedStatement.executeQuery() method. The SQL used by prepareStatement is precompiled ensuring that all parameters sent to underlying database are treated as literal value and not SQL statement/query language, ensuring that no SQL code can be injected using an untrusted parameter.

Ultimately, the security payoff with using prepared statements is that the database will ensure that parameters are automatically escaped

Page 43: Understanding sql

END OF THE SLIDEHACKTHENORTH.ORG

References:

HackplainingOWASP FoundationCodeBashing