


從PHP內(nèi)核層面防范PHP WebShell
[目錄]
1. 簡述
2. php的執(zhí)行流程
3. php的生命周期
4. php源代碼分析以及功能性代碼的實(shí)現(xiàn)
5. 總結(jié)
6. 參考資料
一、簡述
依據(jù)php特定運(yùn)行環(huán)境、php某些特定函數(shù)缺陷、php普通函數(shù)可以實(shí)現(xiàn)變化多端的php
webshell,php版本的scanwebshell也不是太給力。php webshell功能最大化就是實(shí)現(xiàn)文件、
目錄、命令、數(shù)據(jù)庫等操作,這些都是基于php代碼實(shí)現(xiàn)的。把相關(guān)功能化的php函數(shù)運(yùn)行參
數(shù)提取出來,然后做一個判斷,這樣就能從本質(zhì)上防范php webshell,在php這個層面實(shí)現(xiàn)
其安全的最大化。這里介紹下通過編寫php擴(kuò)展來實(shí)現(xiàn)這個思路,當(dāng)然需要的話也可以重新
編譯php源代碼來實(shí)現(xiàn)。
首先我們了解下php的執(zhí)行流程、php生命周期,接下來通過分析具體函數(shù)的php源代碼
來實(shí)現(xiàn)功能性代碼。
二、php的執(zhí)行流程
2.1 scanner
將PHP代碼轉(zhuǎn)換為Tokens,詳見代碼Zend/zend_language_scanner.l。
2.2 parser
將Tokens轉(zhuǎn)換成表達(dá)式,詳見代碼Zend/zend_language_parser.y。
2.3 compile
將表達(dá)式編譯成opcode。opcode存放在op_array中。
2.4 execute
Zend Engine調(diào)用zend_execute來執(zhí)行op_array,輸出結(jié)果。
三、php的生命周期
3.1 STARTUP
1、初始化引擎和核心組件。
2、解析php.ini。
3、初始化靜態(tài)構(gòu)建的模塊(MINIT)。
4、初始化共享模塊(MINIT)。
3.2 ACTIVATION
1、初始化環(huán)境變量、變量。
2、激活靜態(tài)構(gòu)建的模塊(RINIT) 。
3、激活共享模塊(RINIT) 。
3.3 RUNTIME
1、編譯和執(zhí)行php.ini中auto_prepend_file選項(xiàng)指定的文件。
2、編譯和執(zhí)行所請求的文件。
3、編譯和執(zhí)行php.ini中auto_append_file選項(xiàng)指定的文件。
3.4 DEACTIVATION
1、調(diào)用用戶指定的退出函數(shù)。
2、銷毀對象實(shí)例。
3、停用模塊(RSHUTDOWN)。
4、清空輸出。
5、清理環(huán)境。
6、釋放剩余的非持久內(nèi)存。
3.5 SHUTDOWN
1、關(guān)閉啟動的全部模塊(MSHUTDOWN)。
2、關(guān)閉引擎。
四、php源代碼分析以及功能性代碼的實(shí)現(xiàn)
php函數(shù)分為兩種:一種是Zend的函數(shù),這類函數(shù)數(shù)量比較少,比如eval函數(shù)。第二種
是由PHP_FUNCTION宏編寫的,這類函數(shù)數(shù)量比較多,比如system函數(shù)。實(shí)現(xiàn)對兩類函數(shù)在提
取運(yùn)行時的參數(shù)的方式也不相同,比如處理eval函數(shù)用重寫zend_compile_string的方式,
而處理system函數(shù)則對HashTable操作。下邊就以eval函數(shù)和system函數(shù)為例進(jìn)行分析、代
碼實(shí)現(xiàn)。
4.1 eval函數(shù)代碼分析與代碼實(shí)現(xiàn)
首先我們看php源代碼中eval函數(shù)是如何實(shí)現(xiàn)的,部分代碼如下:
// PHPSRC/Zend/zend_vm_def.h
if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
inc_filename = &tmp_inc_filename;
}
case ZEND_EVAL: {
/* 調(diào)用zend_make_compiled_string_deion函數(shù) */
char *eval_desc = zend_make_compiled_string_deion("eval()"d code" TSRMLS_CC);
/* 調(diào)用zend_compile_string函數(shù) */
new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC);
efree(eval_desc);
}
/* 執(zhí)行op_array */
zend_execute(new_op_array TSRMLS_CC);
//PHPSRC/Zend/zend.c
#define COMPILED_STRING_DEION_FORMAT "%s(%d) : %s"
ZEND_API char *zend_make_compiled_string_deion(char *name TSRMLS_DC)
{
zend_spprintf(&compiled_string_deion, 0, COMPILED_STRING_DEION_FORMAT, cur_filename, cur_lineno, name);
return compiled_string_deion; //返回值包含"eval()"d code"字符串
}
//PHPSRC/Zend/zend_compile.c
ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯
- 解決Centos7雙系統(tǒng)后丟失windows啟動項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解