关于SQL漏洞注入(Ado.Net)
SQL漏洞注入是常见的一种攻击方式,我们可以通过一些简单的方式来预防。看一下我们经常写的代码:
1: /// <summary>
2: /// 不安全的登录代码
3: /// </summary>
4: /// <param name="sender"></param>
5: /// <param name="e"></param>
6: private void button2_Click(object sender, EventArgs e)
7: {
8: string connString = "server=.;database=userinfo;uid=sa;pwd=123456";
9: using (SqlConnection conn = new SqlConnection(connString))
10: {
11: conn.Open();
12: string sql = string.Format("select * from userinfo where username = '{0}' and userpwd='{1}'", textBox1.Text, textBox2.Text);
13: using (SqlCommand cmd = new SqlCommand(sql, conn))
14: {
15: using (SqlDataReader reader = cmd.ExecuteReader())
16: {
17: if (reader.Read())
18: {
19: MessageBox.Show("Success!");
20: }
21: else
22: {
23: MessageBox.Show("Error");
24: }
25: }
26: }
27: }
28: }
数据库的结构:
运行程序:
SQL漏洞注入:
方式一(知道用户名):
当在用户名文本框中输入 tom ’ -- 点击登录按钮:
原因是生成后的SQL成了如下形式:
1: select * from userinfo where username = 'tom ' --' and userpwd=''
--是SQL中的注释
方式二(不知道用户名密码):
当在用户名文本框中输入 ' or 1=1 -- 点击登录按钮:
生成后的SQL:
1: select * from userinfo where username = '' or 1=1 --' and userpwd=''
--依然是注释,但是or促成了1=1条件的永远成立。
预防方式一(使用带参数的SQl):
1: /// <summary>
2: /// 安全登录
3: /// </summary>
4: /// <param name="sender"></param>
5: /// <param name="e"></param>
6: private void button3_Click(object sender, EventArgs e)
7: {
8: try
9: {
10: string connString = "server=.;database=userinfo;uid=sa;pwd=123456";
11: using (SqlConnection conn = new SqlConnection(connString))
12: {
13: conn.Open();
14: string sql = "select * from userinfo where username = @id and userpwd= @pwd";
15: using (SqlCommand cmd = new SqlCommand(sql, conn))
16: {
17: cmd.Parameters.Add(new SqlParameter("@id", textBox1.Text));
18: cmd.Parameters.Add(new SqlParameter("@pwd", textBox2.Text));
19: using (SqlDataReader reader = cmd.ExecuteReader())
20: {
21: if (reader.Read())
22: {
23: MessageBox.Show("Success!");
24: }
25: else
26: {
27: MessageBox.Show("Error");
28: }
29: }
30: }
31: }
32: }
33: catch (Exception ex)
34: {
35: MessageBox.Show(ex.Message.ToString());
36:
37: }
38: }
运行:
方式二(使用存储过程):
存储过程:
1: create proc findUser
2: @name nvarchar(50),
3: @pwd nvarchar(50)
4: as
5: select * from userinfo where username = @name and userpwd = @pwd
代码:
1: /// <summary>
2: /// 安全登录
3: /// </summary>
4: /// <param name="sender"></param>
5: /// <param name="e"></param>
6: private void button3_Click(object sender, EventArgs e)
7: {
8: try
9: {
10: string connString = "server=.;database=userinfo;uid=sa;pwd=123456";
11: using (SqlConnection conn = new SqlConnection(connString))
12: {
13: conn.Open();
14: using (SqlCommand cmd = new SqlCommand("finduser", conn))
15: {
16: cmd.CommandType = CommandType.StoredProcedure;
17: cmd.Parameters.Add(new SqlParameter("@name", textBox1.Text));
18: cmd.Parameters.Add(new SqlParameter("@pwd", textBox2.Text));
19: using (SqlDataReader reader = cmd.ExecuteReader())
20: {
21: if (reader.Read())
22: {
23: MessageBox.Show("Success!");
24: }
25: else
26: {
27: MessageBox.Show("Error");
28: }
29: }
30: }
31: }
32: }
33: catch (Exception ex)
34: {
35: MessageBox.Show(ex.Message.ToString());
36:
37: }
38: }