• 使用参数化查询防止SQL注入漏洞


    SQL注入漏洞曾经是Web应用程序的噩梦,CMS、BBS、Blog无一不曾受其害。

    SQL注入的原理
    以往在Web应用程序访问数据库时一般是采取拼接字符串的形式,比如登录的时候就是根据用户名和密码去查询:

    string sql = "SELECT TOP 1 * FROM [User] WHERE UserName = ‘” + userName + “‘ AND Password = ‘” + password + “‘”;

    其中userName和password两个变量的值是由用户输入的。在userName和password都合法的情况下,这自然没有问题,但是 用户输入是不可信的,一些恶意用户只要用一些技巧,就可以绕过用户名、密码登录。

    假设password的值是”1′ or ‘1′ = ‘1“,userName的值随便取,比如是”abc”,那变量sql的 值就是:


    "SELECT TOP 1 * FROM [User] WHERE UserName = ‘abc’ AND Password = ‘1′ or ‘1′ = ‘1′”

    由于’1′ = ‘1′恒为真,因此只要User表中有数据,不管UserName、Password的值是否匹配,这条SQL命令准能查出记录来。就这样,登录系统就被 破解了。

    以往的防御方式
    以前对付这种漏洞的方式主要有三种:

    字符串检测:限定内容只能由英文、数字等常规字符,如果检查到用户输入有特殊字符,直接拒绝。但缺点是,系统 中不可避免地会有些内容包含特殊字符,这时候总不能拒绝入库。
    字符串替换:把危险字符替换成其他字符,缺点是危险字符可能有很多,一一枚举替换相当麻烦,也可能有漏网之 鱼。
    存储过程:把参数传到存储过程进行处理,但并不是所有数据库都支持存储过程。如果存储过程中执行的命令也是通 过拼接字符串出来的,还是会有漏洞。
    参数化查询
    近年来,自从参数化查询出现后,SQL注入漏洞已成明日黄花。

    参数化查询(Parameterized Query 或 Parameterized Statement)是访问数据库时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值。

    在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成SQL指令的编译后,才 套用参数运行,因此就算参数中含有指令,也不会被数据库运行。Access、SQL Server、MySQL、SQLite等常用数据库都支持参数化查询。

    在ASP程序中使用参数化查询
    ASP环境下的参数化查询主要由Connection对象和Command对象完 成。

    Access数据库只支持匿名参数,在传入参数的位置用问号代替即可。SQL Server数据库虽然支持匿名和非匿名的参数,但是在ASP中也仅能使用匿名参数。

    var conn = Server.CreateObject("ADODB.Connection");
    conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("Test.mdb");
    conn.Open();

    var cmd = Server.CreateObject(“ADODB.Command”);
    cmd.ActiveConnection = conn;
    cmd.CommandType = 1;
    cmd.CommandText = “SELECT TOP 1 * FROM [User] WHERE UserName = ? AND Password = ?“;
    cmd.Parameters.Append(cmd.CreateParameter(”@UserName”, 200, 1, 20, “user01″));
    cmd.Parameters.Append(cmd.CreateParameter(”@Password”, 200, 1, 16, “123456″));

    var rs = cmd.Execute();
    Response.Write(rs(”UserId”).value);

    rs.Close();
    conn.Close();

    在ASP.NET程序中使用参数化查询
    ASP.NET环境下的查询化查询也是通过Connection对象和Command对象完成。如果数据库是SQL Server,就可以用有名字的参数了,格式是“@”字符加上参数名。

    SqlConnection conn = new SqlConnection("server=(local)\\SQL2005;user id=sa;pwd=12345;initial catalog=TestDb");
    conn.Open();

    SqlCommand cmd = new SqlCommand(“SELECT TOP 1 * FROM [User] WHERE UserName = @UserName AND Password = @Password“);
    cmd.Connection = conn;
    cmd.Parameters.AddWithValue(”UserName”, “user01″);
    cmd.Parameters.AddWithValue(”Password”, “123456″);

    SqlDataReader reader = cmd.ExecuteReader();
    reader.Read();
    int userId = reader.GetInt32(0);

    reader.Close();
    conn.Close();

    MySQL的参数格式与SQL Server有点区别,是以“?”加上参数名。

    MySqlConnection conn = new MySqlConnection("server=127.0.0.1;uid=root;pwd=12345;database=test;");
    conn.Open();

    MySqlCommand cmd = new MySqlCommand(“SELECT * FROM `User` WHERE UserName = ?UserName AND Password = ?Password LIMIT 1″);
    cmd.Connection = conn;
    cmd.Parameters.AddWithValue(”UserName”, “user01″);
    cmd.Parameters.AddWithValue(”Password”, “123456″);

    MySqlDataReader reader = cmd.ExecuteReader();
    reader.Read();
    int userId = reader.GetInt32(0);

    reader.Close();
    conn.Close();

    本篇文章来源于 站长资讯网 原文链接:http://www.chinahtml.com/1006/asp-127561481718846.html

  • 相关阅读:
    Android开发 使用 adb logcat 显示 Android 日志
    【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410
    C语言 结构体相关 函数 指针 数组
    C语言 命令行参数 函数指针 gdb调试
    C语言 指针数组 多维数组
    Ubuntu 基础操作 基础命令 热键 man手册使用 关机 重启等命令使用
    C语言 内存分配 地址 指针 数组 参数 实例解析
    CRT 环境变量注意事项
    hadoop 输出文件 key val 分隔符
    com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Too many connections
  • 原文地址:https://www.cnblogs.com/WestGarden/p/3138356.html
Copyright © 2020-2023  润新知