1. 程式人生 > >一道簡單的SQL注入題

一道簡單的SQL注入題

這是我真正意義上來說做的第一道SQL題目,感覺從這個題目裡還是能學到好多東西的,這裡記錄一下這個題目的writeup和在其中學到的東西
link:https://www.ichunqiu.com/battalion Web分類下的SQL

嘗試SQL注入

進入這個模擬環境之後,會得到一個提示為flag在資料庫中,這時候檢視url欄可以發現

嗯這個就有SQL注入內味了,然後試一下id=2或者id=3,發現id=2時候可以出來提示為test,然後再往後就什麼都不出來了,這時候我先假裝id後面的東西是一個數字變數,輸入id=1 and 1=1,發現網頁給出提示是這是SQL注入程式碼,這說明這個網站是有對SQL注入做基本的防護的,所以現在的問題就變成了如何繞過伺服器的過濾規則。

對過濾or、and、xor、not的繞過

對這些的繞過一般的操作是

  • and = &&
  • or = ||
  • xor = | # 異或
  • not = !
    現在我們換一下把輸入變成id=1 && 1=1,發現並沒有報錯,這說明我們成功進行了注入的第一步。這時候我們可以發現,很有可能該資料庫僅對我們展示了表中某一列的資料,所以現在就要判斷這個表到底有幾列,這裡使用的方法是order by。url裡輸入id=1 order by 1,報錯提示這是sql注入程式碼,所以現在要進行進一步的繞過

SQL關鍵字過濾繞過

  • 改變大小寫:例如select變為SELect(本題中沒用)
  • 新增內聯註釋:把一些MYSQL的語句放在/*!...*/中,例如/*!order*/(本題中沒用)
  • 雙寫關鍵字:一些waf中替換使用的是replace()函式,因此可以輸入selselectect,在經過waf處理後變為select(本題中沒用)
  • 空格過濾繞過:有些waf會過濾掉注入中的空格導致無法正常允許,這裡可以把空格用/**/,反單引號,(),回車等進行代替(本題中暫時不用考慮)
  • 等號繞過:使用like和rlike模擬=的功能,在不新增萬用字元%時候,like xxxrlike xxx= xxx是等價的(本題中暫不用考慮)
  • 新增<>或者//:因為有的waf會對<>或//進行過濾,所裡可以利用這一點,使用sel<>ect
    進行繞過(本題有用)
    現在進行分割,注意分割時候order不要分割為了or<>der因為這樣又會引入or,現在我們輸入ord<>er by x進行嘗試,發現最多到order by 3就停止了,這說明這個表只有3列。現在我們就需要找出具體的flag位置,這就涉及到對mysql資料庫結構的瞭解。

查詢flag

MYSQL資料庫

Mysql資料庫裡面有一個數據庫叫information_schema,這個資料庫中很多有用的資訊都存在這個裡面

  • schemata表裡面儲存了不同資料庫的資訊,如下所示:
  • tables表裡面儲存著每個資料庫中包含的所有的表的資訊,如下所示:
  • columns表裡面儲存著每個資料庫中列的資訊,如下所示:

檢視資料庫資訊

知道這些東西之後,我們現在要找flag,我認為flag多半是在這個資料庫裡面,首先我們檢視一下當先資料庫的名稱,因為已知查詢到的資料是3列,現在我們要計算,輸出在前端的到底是哪一列的資料,這裡我們構造一個payload為?id=1 un<>ion sel<>ect 1,2,3,發現輸出的有2,那麼可以肯定輸出在前端的就是第二列。
現在我們想要知道這個表在哪個資料庫,所以就可以構造一個payload為?id=1 un<>ion sel<>ect 1,database(),3,得到前端的返回結果為

現在我們就要查詢這個sqli資料庫中存在哪些表,在前面我們說過,表的資訊存在tables中,所以這裡構造一個payload為?id=1 un<>ion sel<>ect 1,table_name,3 from information_schema.tables whe<>re table_schema='sqli',然後可以得到該資料庫中有兩張表,一個是info,一個是users

現在我們分別查一下這兩個表裡面都有哪些列,資訊從columns裡面查到,這時候我們可以構造payload為?id=1 un<>ion sel<>ect 1,column_name,3 from information_schema.columns where table_schema='sqli' an<>d table_name='users'?id=1 un<>ion sel<>ect 1,column_name,3 from information_schema.columns where table_schema='sqli' an<>d table_name='info',分別如下所示:

找到flag

好吧看了一下列名稱,竟然都有flag這個東西,那隻能一個表一個表找了,首先找一下第一個表users,這時候我們可以構造payload為?id=1 un<>ion sel<>ect 1,flag_9c861b688330,3 fr<>om users,但是發現並出不來任何東西。。感到疑惑,好吧那就試下一個構造payload為?id=1 un<>ion sel<>ect 1,flAg_T5ZNdrm,3 fr<>om info,這時候出來結果了,如下所示:

然後複製這個flag交差,就ok啦!

感想

這是第一次做sql注入的題,雖然這個題比較簡單,但是總的來說我還是學到了不少東西的,比如Mysql資料庫中的表結構和sql注入的繞過等,我覺得還是很有教育意義的