Hi I've been repeatedly told not to use concatenation in my sql code for fear of an sql-injection attack. However I've tried to crack my own code with No success. Is out even possible to sql-inject through a window form? Please find the relevant piece of code below:
SqlConnection con = new SqlConnection(
"Data Source=PV10\\LOCALSERVER;Initial Catalog=dbtest;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand(
"select * from Creds where Username= '" +
textBox1.Text +
"' and Password='" +
textBox2.Text +
"'",
con);
SqlDataReader dr;
dr = cmd.ExecuteReader();
while(dr.Read())
{
...
}
答案 0 :(得分:2)
Many a great thing can be performed:
Destruction: put *' or 1 = 1; drop table Creds --
into textBox1.Text
and the query will be
select * from Creds where Username= '*' or 1 = 1;
drop table Creds -- and Password=''
you have two queries; the second one drops creds
table
Deletion: put *' or 1 = 1; delete from Creds --
into textBox1.Text
and the query will be
select * from Creds where Username= '*' or 1 = 1;
delete from Creds -- and Password=''
you have two queries; the second one clears creds
table
Espionage: put ' /*
into textBox1.Text
and */ or '*' = '*
into textBox2.Text
and the query will be
select * from Creds where Username= ' ' /* and Password= '*/ or '*' = '*'
this query returns all the users with their passwords. Start monitor/sniffer and read the values returned. Do you want some data from other table? Just put
' union all select SecretField, TopSecretField from Secrets --
into textBox2.Text
and you'll get
select * from Creds where Username= '' and password = ''
union all
select SecretField, TopSecretField from Secrets --'
Hack: can you see a record "Big boss", "Top secret password"? It's very time to login with this
username/password and put
*' or 1 = 1; update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe'--
into textBox1.Text
and the query will be
select * from Creds where Username= '*' or 1 = 1;
update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe' -- and Password=''
again, you have two queries, and it's quite easy to guess what does the second query do; you may want to buy a ticket to Argentina then.
Trick: register youself as d'Artagnan
; such a name being perfectly right when put into query
select * from Creds where Username= 'd'Artagnan' and Password='mypassword'
will cause a syntax error (and most probably resourse leakage - you haven't wraped IDisposable
- Connection
, Command
, Reader
into using
)
Finally, how it should have been done:
// wrap IDisposable into using
// do not hardcode the connection string
using (SqlConnection con = new SqlConnection(/*read the connection string here*/)) {
con.Open();
// Make Sql being readable
// You don't want at least Username field to be returned (you have in textBox1.Text)
string sql =
@"select Permissions, --TODO: put right fields here
Status
from Creds
where PasswordHash = @prm_PasswordHash and -- do not store password as plain text
Username = @prm_UserName";
// wrap IDisposable into using
using (SqlCommand cmd = new SqlCommand(sql, con)) {
// do not store password as a plain text, but as a hash
//TODO: AddWithValue is not the best choice; put actual parameters' types here
cmd.Parameters.AddWithValue("@prm_PasswordHash", ComputeHash(textBox2.Text));
cmd.Parameters.AddWithValue("@prm_UserName", textBox1.Text);
using (dr = cmd.ExecuteReader()) {
while (dr.Read()) {
...
}
}
}
}