• 详解Web应用安全系列(1)注入漏洞之SQL注入


      注入漏洞通常是指在可输入参数的地方,通过构造恶意代码,进而威胁应用安全和数据库安全。常见的注入漏洞包括:SQL注入和XSS跨站脚本攻击。
    这篇文章我们主要讲SQL注入,SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

    一,攻击案例

    1. 添加' or 1=1#获取全部数据

    比如在系统的用户登录页面,用户在前端页面上输入用户名和密码后提交,应用后台可能执行了下面这样一条sql语句。
    var userName= Request.Form["user_name"]; var passwd= Request.Form["password"]; var sql = "select * from user where username='"+userName+"' and password='"+passwd+"' ";

    上面的变量user_name和password的值是由用户提交的,正常情况下,如果用户输入用户名admin和密码123456,那么sql语句是这样的。

    select * from user where username='admin' and password='123456';

    似乎看起来一切正常。

    但是如果用户在用户名处输入'or 1=1#呢,那么实际的sql语句就变成这样了。
    select * from user where username='' or 1=1#' and password='123456';

    因为#符号在sql中是注释符,所以sql server会忽略#后面的语句,因此上面的sql语句等价于:

    select * from user where username='' or 1=1

    因为1=1是个恒等条件,因此上面的sql语句便变成了下面的语句,查询出了全部用户。

    select * from user
    1. 添加';drop table user#删除数据表

    如果说上面的案例还看不出危险,那么如果用户在用户名处输入';drop table user#呢,那么实际的sql语句就变成这样了。
    select * from user where username='';drop table user#' and password='123456';

    因为#符号在sql中是注释符,因此上面的sql语句等价于:

    select * from user where username='';drop table user

    看出危险了吗,数据库会执行两条sql语句,第一条是一个带where条件的查询语句,第二条执行了drop table删除数据表的操作,最终会导致整个数据表被删除,如果数据库没有做好备份,会直接导致数据丢失,非常严重。

    二,防范措施

    通过前面两个案例我们可以看到,SQL注入发生的前提是应用程序直接相信和使用了用户的输入。那么我们有哪些防范措施呢。
    1. 对用户输入进行转义

    永远不要相信用户的输入,对特殊字符(‘ “ \ <> & *)进行转义处理。如果是使用.net,可以使用System.Net.WebUtility.HtmlEncode(string)将用户输入值中包含的特殊字符转义掉。
    var userName= HtmlEncode(Request.Form["user_name"]); var passwd= HtmlEncode(Request.Form["password"]); var sql = "select * from user where username='"+userName+"' and password='"+passwd+"' ";
    1. 参数化查询

    除了对用户输入进行转义之外,数据库也提供了参数化查询的功能来防止SQL注入,参数化查询的原理是:在使用参数化查询的情况下,数据库服务器不会将参数的内容视为sql指令的一部份来处理,而是在数据库完成 sql 指令的编译后,才套用参数运行,因此就算参数中含有具有损的指令,也不会被数据库所运行。
    目前主流的数据库都支持参数化查询,包括:SQL Server,MySQL,Oracle,SQLite和Access。
    参数化查询代码示例如下:
    复制代码
    Private bool ProtectLogin(string userName, string password)
    {
        SqlParameter[] parameters = new SqlParameter[]
        {
            new SqlParameter{ParameterName="@UserName",SqlDbType=SqlDbType.NVarChar,Size=10,Value=userName},
            new SqlParameter{ParameterName="@Password",SqlDbType=SqlDbType.VarChar,Size=20,Value=password}
        };
        int count = (int)SqlHelper.Instance.ExecuteScalar
            ("SELECT COUNT(*) FROM Login WHERE UserName=@UserName AND Password=@password", parameters);
        return count > 0 ? true : false;
    }
    复制代码
    1. 限制web应用的数据库操作权限

    上面两种方案是比较常用的,除此之外,还可以限制web应用的数据库操作权限,比如把drop table等比较高危的操作权限拿掉,只给必需的最小权限。
     
    另外,我最近开发并开源了一个支持免费申请通配符SSL证书的平台:华迅FreeCert,解决了每隔一段时间就要重新申请和部署证书(因为传统的云厂商提供的免费证书一般只有三个月有效期),不支持免费申请通配符证书这两大痛点,欢迎大家注册使用并提供宝贵意见。
  • 相关阅读:
    pycharm连接服务器
    Databend 源码阅读: Storage 概况和 Read Partitions
    开源项目的版本管理:Git的最佳实践
    MySQL 数据库存储引擎
    node笔记记录36process之1
    element-plus的Tour 漫游式引导怎么去绑定Cascader 级联选择器或者它的内容 popper
    TDesign:腾讯的企业级前端框架,对标elementUI和ant-design
    YOLOv5算法改进(14)— 如何去更换主干网络(3)(包括代码+添加步骤+网络结构图)
    干货|小白也能自制电子相册赶紧码住~
    群晖DS220+ 应用小笔记
  • 原文地址:https://www.cnblogs.com/mcgrady/p/18258929