基於pikachu的漏洞學習(三)完結
命令執行&&程式碼執行
原理也是之前說過n次的,觀察下面的輸入
這是一個ping IP的介面,我們結束一個命令,新增一個命令,&&作為分隔符
就會返回相應的結果
下一個是個eval函式,php的執行命令的函式,輸入phpinfo()
沒什麼多說的,就是提供的介面就是執行命令&程式碼的,但是沒有限制能執行哪些命令
檔案包含
檔案包含主要是程式碼複用用的到的,像是網站的導航欄,每個頁面都有,但是程式碼又不能每頁都寫一遍,所以會把導航欄拆分出來成為一個單獨的檔案,然後用require引用一下就ok了
漏洞的原理就是對引用的檔案沒有限制,隨便引用
$html=''; if(isset($_GET['submit']) && $_GET['filename']!=null){ $filename=$_GET['filename']; include "include/$filename";//變數傳進來直接包含,沒做任何的安全限制 }
應該做過濾,比如只能引用這幾個檔案
if($filename=='file1.php' || $filename=='file2.php' || $filename=='file3.php' || $filename=='file4.php' || $filename=='file5.php'){
include "include/$filename";
}
暫時想象不出來什麼情景會需要這個函式
關於需要使用幾個../的問題,多幾個保證穿到根目錄,讀取一些配置檔案,要看看是什麼系統,有沒有那些檔案
./是當前目錄
../是上一級目錄
包含遠端檔案更簡單了,只看網站讓不讓引用了,兩個配置allow_url_fopen,allow_url_include都為on就可以
修改完配置,直接通過url引用外部檔案
本地包含檔案只能讀取一些配置檔案,那麼更進一步就是自己上傳程式檔案再進行包含
檔案上傳
先介紹一個函式
$_FILES()
這是一個預定義的陣列,通過POST方法接收上傳的檔案的資訊,和session陣列類似,session是儲存會話的一些資訊
$_FILES()["file"]["name"] //上傳檔案的名稱 $_FILES()["file"]["type"] //上傳檔案的型別 $_FILES()["file"]["tmp_name"] //儲存在伺服器的檔案的臨時副本的名稱 $_FILES()["file"]["size"] //上傳檔案的大小 $_FILES()["file"]["error"] //報錯
普通使用者上傳都是傳一些圖片啊,文件什麼的,那麼沒有對檔案做驗證,攻擊者上傳個一句話木馬,就會產生危害
檔案驗證也是分為前端和後端驗證
我們說過,前端驗證都是紙老虎,沒有不能繞過的,這個只是最初級的檔案頭檢驗就更別提了
使用js函式
檢驗content-type,此引數是通過http頭獲取的
可以看到此處有兩個content-type,我們需要修改的是下面的,第一個content-type是傳輸例如視訊、圖片、音訊等的特殊編碼格式的說明,傳輸的是二進位制資料,分段傳輸,第二個才是伺服器獲取的檔案型別
這些都是小case,還有檢查檔案頭的,檔案頭就是系統識別如何解釋(?)檔案的特殊編碼,比如
jpg圖片的檔案頭
用010editor開啟jpg格式的圖片
都是以FF D8開頭的,將其刪除,圖片就無法開啟,或者將JFIF對應的編碼4A 46 49 46這一段刪除,檔案也是無法識別的,其它的大家自己測試學習,在系統中,資料都是以二進位制的形式儲存的,並不存在什麼所謂的型別,所以設定了一些檔案頭來選擇以什麼形式來執行,檔案字尾這種就不說了
在傳輸時,只能看到JFIF的文字
直接在圖片編碼縫隙中插入程式碼,失敗,原來,檢查檔案頭這個函式不僅僅檢查檔案頭,還有檔案大小是否匹配
正常上傳圖片,修改content-length大小,原值是10306,上傳失敗
那麼解決方法就是先將程式碼插入圖片再上傳
copy /b images.jpg+p0.php 1.jpg # 生成1.jpg
我們可以看到程式碼被拼接到最後,content-length變為10319,上傳成功
值得注意的是,檔案上傳後被儲存為jpg字尾的檔案,那麼能否按php檔案執行?
不行,所以說只有把圖片按php檔案執行能利用(因為我們插入的是php程式碼)
剛才講到的檔案包含漏洞,include和require兩個函式,include函式在包含時遇到錯誤會繼續執行,也就是說我們可以直接引用圖片,圖片中的程式碼會正常執行,而require在遇到錯誤時不再執行
順便說一下任意檔案下載,原理就是下載的時候傳檔名,這個檔名可以被控制且沒做許可權控制,導致我們可以隨便下載伺服器的檔案,要求知道檔名和路徑,聽起來很簡單,實驗起來也很簡單,但是遇到有價值的利用場景並不容易
越權
我們在執行一些敏感操作時,比如查詢xx使用者的個人隱私資訊,應該判斷請求的使用者是否是請求檢視自己的資訊,當身份和請求不匹配時,就會產生各種許可權控制問題
案例1:
通過提交使用者名稱檢視個人資訊
程式碼中未對當前會話的使用者和請求檢視哪個使用者進行比對,是否是一個人或者許可權是否允許,我們可以通過註冊一些session變數儲存當前使用者資訊
案例2:
兩個使用者,管理員admin具有新增使用者的操作許可權,同理,普通使用者pikachu是否能執行該操作?
首先嚐試訪問新增使用者的頁面,並未對身份進行校驗
在我未登入任何賬號的情況下,訪問該頁面,跳轉登入,說明只對登入態做了校驗,沒有校驗是否是管理員
修改使用者資訊,提交,發現其又跳轉到登入頁面,但是使用者已經成功添加了
反序列化
所謂序列化就是一個函式,通過serialize這個函式把物件轉換為字串,方便傳輸
o代表物件型別,1代表1個變數,多個變數就在後面繼續排,新增一個testt2變數
O:4:"PIKA":2:{s:5:"test1";s:7:"pikachu";s:5:"test2";s:4:"tien";}
物件型別:長度:"類名":類中變數的個數:{型別:長度:"值";型別:長度:"值";......}
class類物件包括函式和變數,序列化後的這一串字元包括變數型別,長度,值,但是物件中的方法並不會被序列化
object(PIKA)#2 (1) { ["test1"]=> string(7) "pikachu" }
我覺得倒是更像一個數組,還是類似session那種,儲存某個物件的一些值
翻了一些講解,什麼魔術方法,不知所云,看的雲裡霧裡
我們在反序列化後的資料就是一串變數,如果程式不進行處理就沒什麼危害了
看下面這個例子
class User
{
public $age = 0;
public $name = '';
public function PrintData()
{
echo 'User '.$this->name.'is'.$this->age.'years old. <br />';
}
}
同樣是一個物件,包含兩個變數和一個函式,賦值
$user = new User();
$user->age = 20;
$user->name = 'day';
序列化
$ser=serialize($user);
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:3:"day";}
反序列化
var_dump(unserialize($ser));
object(User)#2 (2) { ["age"]=> int(20) ["name"]=> string(3) "day" }
關鍵步驟來了,用反序列化的資料重建物件,然後呼叫(函式可重用,屬性值不同)
程式的後臺程式碼反序列化後呼叫了PrintData方法
$user2 = unserialize($ser);
$user2->PrintData();
這個函式是直接echo了變數到頁面,漏洞就出現在這裡,很容易聯想到我們剛學的xss漏洞,只是傳輸的流程不一樣,並不是因為反序列化,也不是因為魔術方法所以存在漏洞,而是通過這種資料傳輸格式,將惡意payload交給某個函式執行,而這個函式將值輸出到前端頁面導致了xss
直接把day這個變數值替換為xss payload,注意字元長度匹配,27個字元
$user2 = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:27:"<script>alert(233)</script>";}');
預期彈框
魔術方法就是會在某些時刻自動呼叫,比如銷燬某些變數會呼叫__destruct()函式,那麼會存在漏洞嗎?也是要看具體執行了什麼程式碼,和普通方法其實沒什麼差別,但是這可能是反序列化漏洞特有的地方
XXE
定義:輸入的惡意xml文件被解析,造成這個什麼xxe漏洞,要求libxml<2.9.0,因為高版本預設是禁止解析外部實體的
xml文件是傳輸和儲存資料的,libxml是解析xml文件的庫
一個基礎的xml文件,看起來和html差不多,還是有本質區別的
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
一個基礎的xxe payload
<!--宣告xml-->
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!--SYSTEM識別符號說明後面的文件是外部實體 f命名該檔案-->
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<!--引用該檔案-->
<x>&f;</x>
產生漏洞的程式碼
$html='';
//考慮到目前很多版本里面libxml的版本都>=2.9.0了,所以這裡添加了LIBXML_NOENT引數開啟了外部實體解析
if(isset($_POST['submit']) and $_POST['xml'] != null){
$xml =$_POST['xml'];
//simplexml_load_string將xml字串轉換為物件,就是方便操作文件內容
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
if($data){
$html.="<pre>{$data}</pre>";
}else{}
}
後端接收了我們的xml字串,解析了我們的輸入,然後發現要引用/etc/passwd這個檔案,就引用並將資料輸出到前端頁面,我們在html文件中引用,比如php檔案,字型檔案,css檔案的介面,只要可控,是不是也可能存在漏洞呢?
SSRF
定義:後端在向不同伺服器請求資源時,如果這個url引數可控,我們就可以請求其內網的資源
這為什麼是一個漏洞呢?因為內網的很多資源都是比較敏感的,對於外網使用者不可見的,一些人經常用它來探測內網資訊收集
獲取檔案
if(isset($_GET['file']) && $_GET['file'] !=null){
$filename = $_GET['file'];
$str = file_get_contents($filename);
echo $str;
}
這個漏洞更像是偏?代理的那麼一個東西??
不安全的url跳轉
我覺得這個漏洞看到名字就知道是什麼意思了,也不用說,只是提醒一下,這個東西也是個漏洞,釣魚用都可以
其它
本次學習的漏洞基本都是由於不安全的輸入導致的,具體的利用方式是後端決定的,如何處理我們的輸入,我們根據其邏輯構造不同的惡意程式碼
講的都很淺,主要是理解原理 ,後面會繼續進階學習
在自學的過程中,動輒幾十甚至上百小時的教程,確實很勸退,短教程又無法讓我們在最開始建立相對完整的體系,對此,只能說,一定要記錄自己的學習進度甚至做學習筆記,在你放棄後再次學習的時候,不需要重頭再來,總是處於反覆入門的狀態