EC Council CASE.NET_Common Application-Level Attacks_lab1.SQL 注入攻擊跟防範

 





一個登入畫面程式
Username:  tester1
Password:  test1
成功登入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Labs.Module1.Lab1
{
    public partial class login : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void Btn_login_Click(object sender, EventArgs e)
        {
            string strcon = ConfigurationManager.ConnectionStrings["accounts"].ConnectionString;

            SqlConnection con = new SqlConnection(strcon);
            SqlCommand cmd = new SqlCommand
                    ("SELECT [firstname],[lastname],[mobile],[email] FROM [accounts] where [uname]='" +
                    UserName.Text + "' AND [password] = '" + txtpwd.Text + "'", con);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            try
            {
                da.Fill(ds);
                if (ds.Tables[0].Rows.Count > 0)
                {
                    Response.Redirect("Index.aspx");
                }
                else
                {
                    Response.Redirect(Request.RawUrl);
                }
            }
            catch
            {
                ds = null;
            }
           
        }
        
    }
}



緊接著登出嘗試用SQL注入的攻擊手法來ByPass
Username:  ' OR 1 = 1; --
Password:   password





成功ByPass登入進來


甚至可以在SQL注入語法
去對方商業資料庫中產生table
' OR 1 = 1; CREATE TABLE XXXXXXX( CID int , NAME nvarchar(50));--

甚至drop db 或其他table等恐怖操作
' OR 1 = 1; --
' OR 1 = 1; CREATE TABLE XXXXXXX( CID int , NAME nvarchar(50));--
' OR 1 = 1 drop.... --;






防範方式
改為參數化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Labs.M1Lab1
{
    public partial class login : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void Btn_login_Click(object sender, EventArgs e)
        {
            string strcon = ConfigurationManager.ConnectionStrings["accounts"].ConnectionString;
            SqlConnection con = new SqlConnection(strcon);
            SqlCommand cmd = new SqlCommand
("SELECT [firstname],[lastname],[mobile],[email] FROM [accounts] where [uname]=@uname AND [password] = @pwd", con);
SqlParameter uname = new SqlParameter("@uname", SqlDbType.VarChar);
SqlParameter pwd = new SqlParameter("@pwd", SqlDbType.VarChar);
uname.Value = UserName.Text;
pwd.Value = txtpwd.Text;
cmd.Parameters.Add(uname);
cmd.Parameters.Add(pwd);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            try
            {
                da.Fill(ds);
            }
            catch
            {
                ds = null;
            }
            if (ds.Tables[0].Rows.Count > 0)
            {
                Response.Redirect("Index.aspx");
            }
            else
            {
                Response.Redirect(Request.RawUrl);
            }
        }

    }
}






也可以改ORM或是寫成Store Procedure(SP寫法也要用參數化)
來看一個MVC的案例


檢視畫面的code
主要是去到Lab1控制器下的InSecureLogin動作方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>eElectronics - HTML eCommerce Template</title>
    <!-- Custom CSS -->
    <link href="~/ViewCSS/css/bootstrap.min.css" rel="stylesheet" />
    <link rel="stylesheet" href="~/ViewCSS/css/owl.carousel.css" />
    <link rel="stylesheet" href="~/ViewCSS/style.css" />
    <link rel="stylesheet" href="~/ViewCSS/css/responsive.css" />
</head>
<body>

    <div id="intro1">
        <div class="container">
            <div class="wrapper">
                <div class="form-signin">
                    <h3 class="form-signin-heading">Login</h3>
                    <hr class="colorgraph"><br>
           <!--<span class="alert"  id="lblerror" style="">Invalid Credentials</span>-->

@model Labs.Models.account

@{
    //ViewBag.Title = "login";
    //Layout = "~/Shared/Views/_ViewStart.cshtml";
}


@using (Html.BeginForm("InSecureLogin", "Lab1"))


{
    {
                    @Html.ValidationSummary(true)
        {
                    <fieldset>
                       
                           
                            @Html.TextBoxFor(model => model.uname, new { placeholder = "User Name", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.uname)

                        

                        
                          
                            @Html.PasswordFor(Model => Model.password, new { placeholder = "Password", @class = "form-control" })

                            @Html.ValidationMessageFor(model => model.password)

                        

                        <input type="submit" value="login" />
                        @ViewBag.data
                    </fieldset>
        }

    }
}
                    </div>
            </div>
        </div>
    </div>

    <!-- jQuery sticky menu -->
    <script src="~/ViewCSS/js/Jquery.min.js"></script>
    <script src="~/ViewCSS/js/bootstrap.min.js"></script>
    <script src="~/ViewCSS/js/owl.carousel.min.js"></script>
    <script src="~/ViewCSS/js/jquery.sticky.js"></script>

    <!-- jQuery easing -->
    <script src="~/ViewCSS/js/jquery.easing.1.3.min.js"></script>

    <!-- Main Script -->
    <script src="~/ViewCSS/js/main.js"></script>

</body>
</html>


Lab1控制器的code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Labs.Models;
using System.Data;

namespace Labs.Controllers
{
    public class Lab1Controller : Controller
    {
        EntitiyConn db = new EntitiyConn();
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Login()
        {
            return View();

        }


        [HttpPost]


        public ActionResult SecureLogin(account Mlog)
        {
            /* User_Login rs = new User_Login();
            // var pass = from m in db.registers where m.emailid == li.Emailid select m.userpassword;  
            var pass = from m in db.User_Login where m.Uname == Mlog.Uname && m.password == Mlog.password select m;

            if (pass.Count() > 0) return View("Index");
            else return View("Login"); */

            account rs = new account();
            // var pass = from m in db.registers where m.emailid == li.Emailid select m.userpassword;  
            var pass = from m in db.accounts where m.uname == Mlog.uname && m.password == Mlog.password select m;

            if (pass.Count() > 0) return View("Index");
            else return View("Login");



        }

        public ActionResult Logout()
        {
            return Redirect("Login");

        }
        [HttpPost]
        public ActionResult InSecureLogin(account acc)
        {

            string strcon = ConfigurationManager.ConnectionStrings["SqlConn1"].ConnectionString;
            SqlConnection con = new SqlConnection(strcon);
            SqlCommand cmd = new SqlCommand
                    ("SELECT [Uid],[firstname],[lastname],[mobile],[email]FROM [ECSPLabs].[dbo].[accounts] where [uname]='" +
                    acc.uname + "' AND [password] = '" + acc.password + "'", con);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            try
            {
                da.Fill(ds);
            }
            catch
            {
                ds = null;
            }
            if (ds.Tables[0].Rows.Count > 0)
            {
                acc.uid = Convert.ToInt16(ds.Tables[0].Rows[0][0].ToString());
                Session["UserId"] = ds.Tables[0].Rows[0][0];
                return View("Index");
            }
            else
            {
                return View("Login");
            }
        }
    }
}


這邊一樣這種直接透過組字串方式是最危險的

Username:  ' OR 1 = 1; --
Password:   password
都能夠直接By Pass 登入的查檢

這邊我們改將表單打向SecureLogin的動作方法
@using (Html.BeginForm("InSecureLogin", "Lab1"))
取代為
@using (Html.BeginForm("SecureLogin", "Lab1"))

當我們執行時就會發現EF 基於ORM 機制
其實會自動將SQL注入危險給解決掉。












留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header