文章僅為一段時(shí)候清算的php安然代碼審計(jì)筆記總結(jié),一個(gè)闡發(fā)框架,沒有實(shí)例化闡發(fā)。
1、東西篇
編纂器(notepad++,editplus,UE等等,看小我習(xí)慣)
TommSearch(字符串檢索) || grep
HttpProtocolDebugger(http和談?wù){(diào)試器)
Fiddler(闡發(fā)包,改包)
Seay PHP代碼審計(jì)東西(php-code-audit闡發(fā)輔助)
幾個(gè)有趣的項(xiàng)目
dvwa(代碼審計(jì)測(cè)試平臺(tái))
phpmvs
php security audit check
PHP Vulnerability Hunter
2、函數(shù)篇
addslashed()添加反斜杠
stripslashed()往掉落反斜杠
get_magic_quotes_gpc() 鑒定是不是開啟gpc
expode(".",$array)豆割成數(shù)組
is_numeric()鑒定是不是為數(shù)字
sizeof()鑒定長度
trim() 往除字符串開首和末尾的空格或其他字符
system() 輸出并返回最后一行shell成果。
exec() 不輸出成果,返回最后一行shell成果,所有成果可以保留到一個(gè)返回的數(shù)組里面。
passthru() 只調(diào)用號(hào)令,把號(hào)令的運(yùn)行成果原樣地直接輸出到尺度輸出設(shè)備上。
EscapeShellCmd(),把一個(gè)字符串中所有可能瞞過Shell而往履行別的一個(gè)號(hào)令的字符轉(zhuǎn)義。這些字符在Shell中是有特別含義的,象分號(hào)(;),重定向(>)和從文件讀進(jìn) (<)等。
EscapeShellArg() 。在給定的字符串兩邊加上單引號(hào),并把字符串中的單引號(hào)轉(zhuǎn)義,如許這個(gè)字符串便可以安然地作為號(hào)令的參數(shù)。
用popen()函數(shù)打開過程
上面的編制只能簡單地履行號(hào)令,卻不克不及與號(hào)令交互。但有些時(shí)辰必需向號(hào)令輸進(jìn)一些東西,如在增加Linux的系統(tǒng)用戶時(shí),要調(diào)用su來把當(dāng)前用戶換到root才行,而su號(hào)令必需要在號(hào)令行上輸進(jìn)root的暗碼。這類環(huán)境下,用上面提到的編制明顯是不可的。
popen ()函數(shù)打開一個(gè)過程管道來履行給定的號(hào)令,返回一個(gè)文件句柄。既然返回的是一個(gè)文件句柄,那么便可以對(duì)它讀和寫了。在PHP3中,對(duì)這類句柄只能做單一 的把持模式,要么寫,要么讀;從PHP4開端,可以同時(shí)讀和寫了。除非這個(gè)句柄是以一種模式(讀或?qū)?打開的,不然必需調(diào)用pclose()函數(shù)來封鎖 它。
例子1:
/* PHP中若何增加一個(gè)系統(tǒng)用戶
下面是一段例程,增加一個(gè)名字為james的用戶,
root暗碼是 verygood。僅供參考
*/
$sucommand = "su --login root --command";
$useradd = "useradd ";
$rootpasswd = "verygood";
$user = "james";
$user_add = sprintf("%s "%s %s"",$sucommand,$useradd,$user);
$fp = @popen($user_add,"w");
@fputs($fp,$rootpasswd);
@pclose($fp);
require在被包含文件有弊端代碼時(shí)將不再往下履行
include在被包含文件有弊端代碼時(shí)仍然往下履行
htmlspecialchars() 函數(shù)把一些預(yù)定義的字符轉(zhuǎn)換為 HTML 實(shí)體。
預(yù)定義的字符是:
&(和號(hào)) 成為 &
"(雙引號(hào)) 成為 "
' (單引號(hào)) 成為 '
<(小于) 成為 <
>(大年夜于) 成為 >
move_uploaded_file() 函數(shù)將上傳的文件移動(dòng)到新位置。
extract() 函數(shù)從數(shù)組中把變量導(dǎo)進(jìn)到當(dāng)前的符號(hào)表中。
對(duì)數(shù)組中的每個(gè)元素,鍵名用于變量名,鍵值用于變量值。
第二個(gè)參數(shù) type 用于指定當(dāng)某個(gè)變量已存在,而數(shù)組中又有同名元素時(shí),extract() 函數(shù)若何對(duì)待如許的沖突。
本函數(shù)返回成功設(shè)置的變量數(shù)量。
語法
extract(array,extract_rules,prefix)
parse_str() 函數(shù)把查詢字符串解析到變量中. (常見于變量籠蓋縫隙)
語法
parse_str(string,array)
參數(shù) 描述
string 必需。劃定要解析的字符串。
array 可選。劃定存儲(chǔ)變量的數(shù)組名稱。該參數(shù)唆使變量存儲(chǔ)到數(shù)組中。
針對(duì)變量指定報(bào)復(fù)打擊
不利用foreach遍歷$_GET變量,改用$_GET[(index)]
eval() 函數(shù)把字符串遵循 PHP 代碼來計(jì)較。該字符串必需是合法的 PHP 代碼,且必需以分號(hào)結(jié)尾。
假定沒有在代碼字符串中調(diào)用 return 語句,則返回 NULL。假定代碼中存在解析弊端,則 eval() 函數(shù)返回 false。
preg_replace 履行一個(gè)正則表達(dá)式的搜刮和替代
/e參數(shù)履行代碼
3、縫隙篇
-----------------------------------------------
[1].Sql-Injection
寄望:cookie及x-forward-for,寬字節(jié),報(bào)錯(cuò)打針等
發(fā)掘縫隙參考
變量
$_GET[""],$_POST[""],$_COOKIE[""], $SERVER[""]
數(shù)據(jù)庫把持函數(shù)
mysql_query()
數(shù)字型注進(jìn)防備:
1.is_numeric() ctype_digit() intval()
2.str_length()肯定長度
字符型注進(jìn)防備:
1.mysql_real_escape_string()
2.數(shù)據(jù)庫查詢語句前加@防爆錯(cuò)
3.str_length()肯定長度
-----------------------------------------------
[2].Command-Execution
函數(shù):
system(),passthru(),popen(),exec()
數(shù)據(jù)庫把持函數(shù):
exec,system,popen,passthru,proc_open,shell_exec
履行號(hào)令管道符 % | >
測(cè)試如0 | dir c:
|| 雙豎線的感化,前面語句履行弊端則履行后面語句
如xx"+||+whoami+||+echo
-----------------------------------------------
[3].File-Inclusion
函數(shù):
include(),require(),include_once(),require_once()
長途文件包含縫隙要求
allow_url_fopen() allow_url_include() file_get_contents()
繞過:zlib://和ogg://
5.2.0以后版本
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+ //
@eval(file_get_contents('php://input')); //POST phpinfo();
共同%00截?cái)?,新版本主?dòng)轉(zhuǎn)義\0
-----------------------------------------------
[4].CSRF
CSRF防備策略
1>驗(yàn)證http-referer字段
安然性低,易被捏造
2>在要求地址中添加token并驗(yàn)證
token可在用戶登錄后存放在session中,每次要求時(shí)將token從session中掏出,往要求的token對(duì)比以防備CSRF
GET編制:http://url/?=token
假定一個(gè)網(wǎng)站接管要求處所比較多,則在每次頁面加載時(shí)遍歷全部dom樹,在dom中每個(gè)a和form標(biāo)簽后加進(jìn)token
但在動(dòng)態(tài)頁面加載后產(chǎn)生的html代碼,則需要以硬編碼的情勢(shì)手工添加
這類編制安然性弱點(diǎn)在于,如在論壇等交互比較頻繁的處所hacker可機(jī)關(guān)環(huán)境盜取token并進(jìn)而機(jī)關(guān)csrf報(bào)復(fù)打擊
故手工封鎖referer
3>在HTTP頭中自定義屬性并進(jìn)行驗(yàn)證。經(jīng)由過程XMLHttpRequest類。
凡是常利用于Ajax編制對(duì)頁面局部的異步刷新
但適應(yīng)性一般,對(duì)已有的網(wǎng)站架構(gòu)局限性較大年夜
-----------------------------------------------
[5].XSS(Cross Site Script)
反射型與存儲(chǔ)型
節(jié)制$_GET,$_POST,$_COOKIE 各類傳進(jìn)的變量
利用htmlspecialchars()函數(shù)進(jìn)行根本過濾
連絡(luò)CSRF實(shí)現(xiàn)主動(dòng)化操縱
-----------------------------------------------
[6].File_Upload
函數(shù):move_uploaded_file()
變量:$_FILES
php文件上傳操縱form表單進(jìn)行文件上傳時(shí)必需為post利用multipart/form-data才能完全的傳遞文件數(shù)據(jù)
php操縱$_FILES系統(tǒng)函數(shù)的相干參數(shù)與函數(shù)move_upload_file函數(shù)來實(shí)例把由$_FILES全局變量生成的姑且文件移動(dòng)到指定目次完成文件的上傳
$_FILES['files']['name']客戶端文件的原名稱
$_FILES['files']['type']文件的MIME類型
$_FILES['files']['size']已上傳文件的大年夜小
$_FILES['files']['tmp_name']儲(chǔ)存的姑且文件名,通常是系統(tǒng)默許
$_FILES['files']['error']該文件上傳到相干的弊端代碼
防備編制:
1>鑒定MIME TYPE文件類型如$_FILES['files']['type']=="image/jpeg",鑒定文件大年夜小,如$_FILES['files']['size']<10000 &&$_FILES['files']['size']>100
2>指定上傳文件名,如依托時(shí)候生成hash(time).jpg等編制
3>按照文件后綴名鑒定文件
如file_ext=substr($filename,$strrpos($filename,'.')+1);
寄望是不是可能有雙擴(kuò)大名,二次上傳沖破等邏輯標(biāo)題問題
4>辦事器測(cè)驗(yàn)測(cè)驗(yàn)襯著文件等編制鑒定是不是為圖片
5>不依托于客戶端js腳本限制上傳文件類型
6>白名單法則
apache辦事器常見上傳安然標(biāo)題問題
1>共同.htaccess操縱上傳
AllOverride ALL 承諾子法則籠蓋父法則
.htaccess添加AddType Application/x-httpd-php .jpg
2>文件名解析縫隙
*.php.123
在.htaccess添加AddHandler php5-script .php,文件名中包含php擴(kuò)大名可以php腳本履行,如x.php.jpg
.php3 .php4擴(kuò)大名
4、建設(shè)篇
1>存眷縫隙信息,及時(shí)更新版本
2>php.ini httpd.conf .htaccess文件建設(shè)
1)safe_mode相干建設(shè)
2)register_globals封鎖
3)open_basedir建設(shè),防備目次遍歷
4)allow_url_fopen封鎖
5)disable_functions建設(shè)
6)magic_quotes_gpc打開
7)error_reporting=E_ALL &~E_NOTICE
8)display_errors=Off避免報(bào)復(fù)打擊者獲得更多信息
9)expose_php=Off隱躲版本信息
3>最小化辦事器其他賬戶權(quán)限
4>第三方安然加固軟件安裝
5>調(diào)用第三方安然防護(hù)文件,建設(shè)php.ini
include_path=".:/php/includes"
auto_pretend_file="anti-inj.php"
auto_appent_file=
5、思路篇
剛開端操練審計(jì)時(shí),拿到一套源碼,頓時(shí)做的工作就是,丟到東西里,往掃敏感的函數(shù),然后往一個(gè)一個(gè)的回溯它,找到進(jìn)口點(diǎn)??墒?,如許審計(jì)很華侈時(shí)候,每次都要在回溯過程中,不竭的往尋覓源碼中定義的一些通用函數(shù)。因?yàn)椴惑w味全部源碼的流程,導(dǎo)致在找這些通用函數(shù)的過 程中華侈了良多的時(shí)候與精力。
所以,我從頭調(diào)劑了我的審計(jì)流程。在拿到源碼以后,先從它開端的處所(通常為根目次下的index文件)遵循履行的挨次往讀代碼,一向到它的初始化內(nèi)容, 和根基功能實(shí)現(xiàn)終了為止。如許,可以明白的體味整套源碼的布局,哪一種函數(shù)文件放在哪個(gè)文件夾下;知道通用函數(shù)放在哪個(gè)文件中。這對(duì)我們?cè)谝院鬄g覽“疑似”有標(biāo)題問題標(biāo)代碼時(shí),有很好的幫忙,例如,在看到一個(gè)通用函數(shù)時(shí),我們可以快速的切換到通用函數(shù)文件,查找這個(gè)函數(shù)的實(shí)現(xiàn)代碼。
注:此處援引點(diǎn)竄唐門三少文章《PHP代碼審計(jì)進(jìn)修總結(jié)》
6、小結(jié)
代碼審計(jì)一如逆向工程,均需要耐煩與細(xì)心。
別的,存眷縫隙發(fā)布平臺(tái)上最新縫隙并跟蹤加以闡發(fā)也是一個(gè)很快晉升本身能力的編制。