深入淺析.NET應(yīng)用程序SQL注入
1.準(zhǔn)備工具:SQL SERVER ,Visual Studio
2.數(shù)據(jù)庫腳本和.net代碼(c#)
3.SqlServer Profiler
SQL腳本代碼:
USE MASTER GO --檢索SQLTMP數(shù)據(jù)庫是否存在 IF EXISTS(SELECT * FROM SYSDATABASES WHERE name = 'SQLTMP') --刪除SQLTMP數(shù)據(jù)庫 DROP DATABASE SQLTMP GO --創(chuàng)建數(shù)據(jù)庫 CREATE DATABASE SQLTMP GO --使用SQLTMP數(shù)據(jù)庫 USE SQLTMP GO -------------創(chuàng)建一張表用來驗(yàn)證SQL注入漏洞---------------- --檢索表是否存在 IF EXISTS(SELECT * FROM SYSOBJECTS WHERE name = 'admin') --刪除表 DROP TABLE admin GO --創(chuàng)建表 CREATE TABLE admin ( id INT PRIMARY KEY IDENTITY(1,1),--設(shè)置主鍵 name VARCHAR(20) NOT NULL,--用戶名 pass VARCHAR(20) NOT NULL--密碼 ) -------------插入一條測(cè)試數(shù)據(jù)--------------------------- INSERT INTO admin VALUES('admin','admin') --查詢插入數(shù)據(jù) SELECT * FROM admin
下面是一段驗(yàn)證用戶名密碼的C#代碼:
<font size="3" color="#ff00ff">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; namespace SQLTmp { class Program { //數(shù)據(jù)庫連接字符串 public static String strCon = "Data Source=.;Initial Catalog=SQLTMP;Integrated Security=True"; //創(chuàng)建數(shù)據(jù)庫連接對(duì)象 static SqlConnection SqlCon = new SqlConnection(strCon); static void Main(string[] args) { Console.WriteLine("請(qǐng)輸入用戶名:"); String name = Console.ReadLine(); Console.WriteLine("請(qǐng)輸入密碼:"); String pass = Console.ReadLine(); try { Program p = new Program(); //打開數(shù)據(jù)庫連接 p.Open(); string sql = "SELECT COUNT(*) FROM admin WHERE name = '"+name+"'AND pass = '"+pass+"'"; SqlCommand sqlcom = new SqlCommand(sql, SqlCon); int i = (int)sqlcom.ExecuteScalar(); if (i > 0) { Console.WriteLine("登錄成功!"); } else { Console.WriteLine("登錄失敗!"); } Console.ReadLine(); } catch (Exception) { throw; } finally { //關(guān)閉數(shù)據(jù)庫連接 pass.Clone(); } } //打開數(shù)據(jù)庫連接 public void Open() { //關(guān)閉狀態(tài)下打開數(shù)據(jù)庫連接 if (SqlCon.State == ConnectionState.Closed) { SqlCon.Open(); } //中斷情況下打開數(shù)據(jù)庫連接 if (SqlCon.State == ConnectionState.Broken) { //關(guān)閉 SqlCon.Close(); SqlCon.Open(); } } //關(guān)閉數(shù)據(jù)庫連接 public void Close() { if (SqlCon.State == ConnectionState.Open || SqlCon.State == ConnectionState.Broken) { SqlCon.Close(); } } } } </font>
我們來測(cè)試一下
輸入正確的賬號(hào)密碼:
admin admin
登錄成功
輸入錯(cuò)誤的賬號(hào)密碼:
test test
登錄失敗
我們?cè)谟脩裘斎?' or 1=1--
密碼:123
會(huì)發(fā)現(xiàn)也能登錄成功!
數(shù)據(jù)庫中沒有這個(gè)賬號(hào)密碼,還會(huì)登錄成功?
why?
0x03剖析
我們來剖析一下SQL語句的運(yùn)行過程
利用我的SQL語句跟蹤工具(SQL Server Profiler)
單擊鏈接
運(yùn)行
我們來看一下輸正確的賬號(hào)密碼SQL語句的樣子
在我們的SQL Server中執(zhí)行看看,有符合條件的數(shù)據(jù)
我們?cè)賮砜纯摧斎脲e(cuò)誤的賬號(hào)密碼SQL語句的樣子
在我們的SQL Server中執(zhí)行看看,沒有符合條件的數(shù)據(jù)
我們?cè)賮砜纯醋詈笠淮蔚妮斎氲馁~號(hào)密碼的SQL語句的樣子
我們來看看圖片中的SQL語句我們的上面的SQL語句對(duì)比一下
<font size="3" color="#ff00ff">SELECT COUNT(*) FROM SQLTMP WHERE name = 'admin' AND pass = 'admin' SELECT COUNT(*) FROM SQLTMP WHERE name = '' or 1=1 -- ' AND pass = '123' </font>
我們會(huì)發(fā)現(xiàn)我們輸入的用戶名變成了空,后面多了or 1=1 --'這又是為什么,什么原因?qū)е碌????/p>
到離這里我們就應(yīng)該看看這一段代碼:
<font size="3" color="#ff00ff"> string sql = "SELECT COUNT(*) FROM admin WHERE name = '"+name+"'AND pass = '"+pass+"'"; </font>
我們可以看出SQL是中的name和pass是變量是用戶輸入的賬號(hào)和密碼
我們來看一下輸入的用戶名:' or 1=1 --
那么用戶如輸入'的時(shí)候就會(huì)自動(dòng)把name = ''閉合
而 or 1=1 將where 條件永遠(yuǎn)成立
--在SQL是注釋的意思會(huì)將后面的SQL語句注釋掉!!!
那么我們就可以這么認(rèn)為SQL語句到最后是這個(gè)樣子的
<font size="3" color="#ff00ff">SELECT COUNT(*) FROM SQLTMP WHERE name = '' or 1=1</font>
0x04防御
有攻擊的方式是會(huì)有防御的方式
據(jù)我所知常用的有倆種方式:
1.通過SQLParameter
好處:預(yù)編譯SQL語句防止被轉(zhuǎn)意
用法:
<font size="3" color="#ff00ff">string sql = "SELECT COUNT(*) FROM admin WHERE name = [url=home.php?mod=space&uid=116087]@name[/url] AND pass = @pass "; //創(chuàng)建SParameter[] SqlParameter[] para = { new SqlParameter("@name",name), new SqlParameter("@pass",pass) }; SqlCommand sqlcom = new SqlCommand(sql, SqlCon); //通過Parameters.addRange方法將para[]放進(jìn)去 sqlcom.Parameters.AddRange(para); int i = (int)sqlcom.ExecuteScalar(); </font>
@符號(hào)代表的參數(shù),我們把拼接的方式換成了參數(shù)的形式
2.存儲(chǔ)過程
1.首先在數(shù)據(jù)庫中創(chuàng)建存儲(chǔ)過程
<font size="3" color="#ff00ff">CREATE PROC Login (@name VARCHAR(20) ,@pass VARCHAR(20)) AS SELECT COUNT(*) FROM admin WHERE name =@name AND pass = @pass GO </font>
2. 調(diào)用存儲(chǔ)過程
<font size="3" color="#ff00ff">SqlParameter[] para = { new SqlParameter("@name",name), new SqlParameter("@pass",pass) }; SqlCommand sqlcom = new SqlCommand(); sqlcom.Connection = SqlCon; sqlcom.CommandText = "Login"; //指定執(zhí)行類型為存儲(chǔ)過程 sqlcom.CommandType = CommandType.StoredProcedure; sqlcom.Parameters.AddRange(para); int i = (int)sqlcom.ExecuteScalar(); </font>
好了,關(guān)于本文給大家介紹的.NET應(yīng)用程序SQL注入就給大家介紹到這里,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的,在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
ASP.NET性能優(yōu)化小結(jié)(ASP.NET&C#)
ASP.NET性能優(yōu)化,提高頁面的執(zhí)行效率與下載速度,等很多需要考慮的細(xì)節(jié),編程人員值得參考下。2011-01-01對(duì)Entity?Framework?Core進(jìn)行單元測(cè)試
這篇文章介紹了對(duì)Entity?Framework?Core進(jìn)行單元測(cè)試的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03ASP.NET中動(dòng)態(tài)控制RDLC報(bào)表
ASP.NET中動(dòng)態(tài)控制RDLC報(bào)表...2006-09-09Asp.Net 無刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路
這篇文章詳細(xì)介紹了無刷新文件上傳并顯示進(jìn)度條的思路和代碼,有需要的朋友可以參考一下2013-06-06在.NET Core類庫中使用EF Core遷移數(shù)據(jù)庫到SQL Server的方法
下面小編就為大家分享一篇在.NET Core類庫中使用EF Core遷移數(shù)據(jù)庫到SQL Server的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12簡(jiǎn)單談?wù)?NET Core跨平臺(tái)開發(fā)
本文給大家詳細(xì)介紹了如何使用.NET Core進(jìn)行跨平臺(tái)開發(fā),包含簡(jiǎn)單的環(huán)境架設(shè)以及配置,以及使用vs進(jìn)行編譯運(yùn)行項(xiàng)目和注意事項(xiàng),有需要的小伙伴可以參考下2016-07-07asp.net下將Excel轉(zhuǎn)成XML檔的實(shí)現(xiàn)代碼
通過Asp.net(C#)應(yīng)用程序讀取本地上傳的Excle文件,存放到DataSet中,通過DataSet中的方法直接生成XML文件.2009-11-11Asp.net Core MVC中怎么把二級(jí)域名綁定到特定的控制器上
這篇文章主要介紹了Asp.net Core MVC中怎么把二級(jí)域名綁定到特定的控制器上,需要的朋友可以參考下2017-06-06