1. 程式人生 > >SQL基本注入演示

SQL基本注入演示

作者:ZERO 所屬團隊:Arctic Shell

參考文獻:《sql注入攻擊與防禦》

使用平臺:pikachu漏洞練習平臺

導語:  在owasp釋出的top10排行榜中注入漏洞一直是危害排名極高的漏洞,資料庫注入一直是web中一個令人頭疼的問題。

  一個嚴重的SQL注入漏洞,可能會直接導致一家公司破產!這並不是戲言,其實SQL注入漏洞最主要的形成原因是在進行資料互動中,當前端的資料傳入後端進行處理時,由於沒有做嚴格的判斷,導致其傳入的“資料”在拼接到SQL語句中之後,由於其特殊性,被當作SQL語句的一部分被執行,從而導致資料庫受損(被脫褲、被刪除、甚至整個伺服器許可權淪陷)。

本文將從web程式的基本原理開始理解SQL注入,然後找到SQL注入利用(本次將演示利用information-schema注入進行一次完整的入侵過程再現)。

0×1: 理解(瞭解)web應用的工作原理在日常web開發中,我們會來開發出許多的web應用來服務於我們的日常生活,隨著人們生活質量的提高,web應用的形式也越來越多,但大部分的web應用依舊有著相同點,他們都具備互動性,且多半是資料庫進行驅動的,在當下的網際網路中,用資料庫驅動的web應用多如牛毛,他們通常含有一個後臺資料庫以及很多頁面,而在這些頁面中包含了利用某種程式語言來寫成的伺服器端指令碼,這些指令碼作用於web頁面來與使用者進行互動時從資料庫中提取特定的資料。

一般的web應用通常分三層,分別是表示層、邏輯層、儲存層。下面我們介紹一下這三層以及互動方式表示層是一個web應用的最高層,將該web應用的具體功能以及資訊呈現給使用者,還可以與其他層進行互動。

邏輯層(中間層)是用來處理細節以達到控制應用的目的。

而儲存層包括資料庫伺服器,用來進行的資訊的檢索和存貯。

通常的互動方式就是表示層向中間層發出請求,中間層通過查詢、檢索儲存層,獲取資訊來響應該請求。這就是一次完成的互動過程。

三層架構有一個基本原則:表示層不能直接於資料層通訊,在三層架構中,所有通訊必須都通過中間層。

0×2:理解SQL注入前面講了那麼多理論的東西,究竟什麼是SQL注入呢?

SQL注入就是構造SQL語句並將他們插入到傳入的引數中發動的攻擊,然後將這些引數遞交給後臺SQL伺服器加以解析並執行。

這裡我將用一個最基本的數字型注入來演示一個基本SQL注入

一個基本的查詢頁面長這樣的:

image.png

我們輸入一個“1”試一試

image.png

這裡可以看出查詢了兩個欄位,猜測hello後的應該是使用者名稱,下面的應該是使用者所對應的郵箱

因此猜想SQL語句的構造可能是這樣的:

select 欄位1,欄位2 from 表 where id =1

那我們如何獲得表的其他資料呢?(俗稱爆表)

這裡就可以來嘗試構造一個利用了:1 or 1=1

(在SQL中or是如果第一個條件和第二個條件中只要有一個成立,則 OR 運算子顯示一條記錄。1=1永久返回為真,所以where後輸入的值將永遠為真)

因為是post方法,我們使用hackbar進行post提交,來遍歷整個表

image.png

一次基礎的SQL注入利用就演示完成了。

0×3:如何找到SQL注入本身我們很難獲取到web應用的原始碼,這樣會導致我們不知道設計者如何設計的,找到SQL注入,這就需要藉助黑客本身的自我思維能力來進行測試。藉助推理來進行測試的一般步驟:向伺服器傳送請求,然後檢視其中的異常來獲取資訊。

通過SQL錯誤來找到SQL注入   在web注入靶場中我們可以通過看原始碼知道這個web應用的構造,來完成利用,而在實際的測試中,碰到的都是是不開源的web應用,導致對於內部構造完全不清楚,在實際的測試中一般黑客採用讓SQL報錯的方式來猜測內部構造,以達到找到注入點的目的。

我將通過字元型注入來演示通過SQL報錯來查詢注入

image.png

字元型注入這類利用的一般方式是:先來閉合測試,構造合法的SQL來欺騙後臺。

利用的一般樣式:xxx (符號閉合) or 1=1(註釋)

通常一個輸入框我們事先並不知道輸入的內容再被傳入時被當做字元還是數字,這時就可以通過報錯來進行判斷,SQL中字元和數字的區別是數字不用’’或者””來進行修飾,而字元則需要,於是我們則需要判斷兩次,先判斷這個輸入框是數字型的還是字元型的在判斷他是用哪個修飾符來進行修飾

image.png

報錯內容提示列名不存在,這個報錯提示我們SQL伺服器認為這個值不是一個數字,那末就是一個列,然後SQL去尋找這個列,然後當然什麼都找不到,就返回報錯了,通過這裡我們可以判斷出應該輸入的型別

接著來判斷修飾符

image.png

查詢後結果

image.png

從報錯提示中可以分析出雙引號並沒有傳遞進資料庫伺服器裡,也就是儲存層,我們再試一個單引號

再次返回報錯,在這個報錯中我們可以看出修飾符已經進入到了SQL伺服器中並執行,說明存在注入點,接著可以來開始進行注入了,知道了該用哪個修飾符進行閉合,這時構造個利用將會變的更加容易。

(每當我們傳遞一個值到SQL構造語句中的時候,如果傳遞的一個值是需要符號修飾的,那末SQL語句會自帶一個符號去進行閉合,例如:傳值為a,到SQL語句中就會使這樣:select xxx,xxx from xxx where id=’a’,那兩個單引號就是SQL構造語句中用來進行引數閉合的,簡單的說,只要你輸入一個需要符號修飾的詞語,後臺就會自動給它加一個修飾符號,這也就是我們為何要把前面進行符號閉合,但是後面就會多了一個‘ 符號,我們直接註釋掉就好了。同樣的方法,利用order by 可以猜測有幾個欄位,道理相同,這裡就不贅述了。)

0×4: 瞭解information_schema    information_schema資料庫是MySQL自帶的,它提供了訪問資料庫元資料的方式。

元資料是關於資料的資料,如資料庫名或表名,列的資料型別,或訪問許可權等。有些時候用於表述該資訊的其他術語包括“資料詞典”和“系統目錄”。

也就是說information_schma可以查到你的所有的搭建的資料庫名、表名和列的資料型別,在一切條件未知的情況下,存在注入點的話我們可以直接嘗試對information_schema進行訪問,從而獲得更多的資訊。

   例如:

        SCHEMATA:提供了當前MySQL例項中所有資料庫的資訊

        TABLES:所有資料庫表的資訊

        CONLUMNS:提供了列資訊

0×5:瞭解union聯合注入既然要從一個資訊資料庫開始注入,也就是另外一個數據庫,我們就不能在當前的資料庫下進行查詢,但是當前資料庫查詢下還存在一個注入點,所以說如何才能同時查詢兩次呢?這個時候我們就可以用到union聯合注入了,而union的作用是將兩個或多個select語句查詢語句結果合併起來

幾個值得注意的地方:

1.UNION必須由兩條或兩條以上的SELECT語句組成,語句之間用關鍵字UNION分隔

2. UNION中的每個查詢的列數(欄位數)必須相同

3. UNION會從查詢結果集中自動去除了重複行

比如:

主查詢:

select username,password form member where name=“zero“ (union查詢)union select id,password form member where id=1

構造 payload:

xx’ union select database(),user()#

說明:

Database():這個是查詢資料庫名稱

user():這個是使用者許可權

image.png

0×6: information_schema注入演示  還是使用字元型注入,在前面的報錯中我們知到了兩個欄位和注入點是單引號,開始注入

首先獲取基本資訊:當前資料庫名稱

xxx’union select database(),user()#

image.png

獲取到當前資料庫名稱:pikachu

通過information_schema來獲取pikachu中有多少個表以及表的名稱

xxx’union select table_schema,table_name from information_schema.tables where table_schema=”pikachu”#

image.png

獲取到表名:users

獲取列:

xxx’union select table_name,column_name from information_schema.columns where table_name=’users’#

image.png

整理獲取到的資訊來獲取密碼:

xxx’union select username,password from users#

image.png

0×7: 總結作為一名Web應用開發人員,一定要對使用者輸入的資料進行嚴格的校驗處理,否則的話,SQL Injection將會不期而至!