深入淺析.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 BasePage類+Session通用用戶登錄權(quán)限控制
判斷用戶是否登錄,常用的方法就是通過Session來控制。2010-05-05
ASP.NET中TextBox使用Ajax控件顯示日期不全的問題解決方法
這篇文章介紹了ASP.NET中TextBox使用Ajax控件顯示日期不全的問題解決方法,有需要的朋友可以參考一下2013-10-10
Asp.Net的FileUpload類實(shí)現(xiàn)上傳文件實(shí)例
這篇文章主要介紹了Asp.Net的FileUpload類實(shí)現(xiàn)上傳文件的方法,以實(shí)例形式講述了上傳文件類的具體實(shí)現(xiàn)方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-11-11
ASP.NET Core項(xiàng)目結(jié)構(gòu)教程(4)
這篇文章主要為大家詳細(xì)介紹了ASP.NET Core項(xiàng)目結(jié)構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
asp.net在iframe中彈出信息并執(zhí)行跳轉(zhuǎn)問題探討
本代碼將實(shí)現(xiàn)在iframe中彈出信息并執(zhí)行跳轉(zhuǎn),感興趣的朋友可以參考下2013-04-04
ASP.NET中CKEditor與CKFinder的配置使用
這篇文章主要介紹了ASP.NET中CKEditor與CKFinder的配置使用的相關(guān)資料,需要的朋友可以參考下2015-06-06
asp.net AutoCompleteExtender的一個(gè)簡單例子代碼
asp.net AutoCompleteExtender的一個(gè)簡單例子代碼2009-12-12
HTTP 錯(cuò)誤 500.19 - Internal Server Error解決辦法詳解
這篇文章主要介紹了HTTP 錯(cuò)誤 500.19 - Internal Server Error解決辦法詳解的相關(guān)資料,這里對(duì)錯(cuò)誤進(jìn)行了詳細(xì)分析及說明該如何解決,需要的朋友可以參考下2016-11-11
asp.net中ADO SQL數(shù)據(jù)庫 筆記匯總 持續(xù)更新中
asp.net中ADO SQL數(shù)據(jù)庫 筆記匯總 持續(xù)更新中,需要的朋友可以參考下2012-07-07

