日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

開(kāi)發(fā)中php安全性要考慮哪些?

1把握整站的結(jié)構(gòu),避免泄露站點(diǎn)敏感目錄

在寫(xiě)代碼之初,我也是像很多老源碼一樣,在根目錄下放上index.php、register.php、login.php,用戶(hù)點(diǎn)擊注冊(cè)頁(yè)面,就跳轉(zhuǎn)到http://localhost/register.php。并沒(méi)有太多的結(jié)構(gòu)的思想,像這樣的代碼結(jié)構(gòu),最大的問(wèn)題倒不是安全性問(wèn)題,而是代碼擴(kuò)展與移植問(wèn)題。

在寫(xiě)代碼的過(guò)程中,我們常要對(duì)代碼進(jìn)行修改,這時(shí)候如果代碼沒(méi)有統(tǒng)一的一個(gè)入口點(diǎn),我們可能要改很多地方。后來(lái)我讀了一點(diǎn)emlog的代碼,發(fā)現(xiàn)網(wǎng)站真正的前端代碼都在模板目錄里,而根目錄下就只有入口點(diǎn)文件和配置文件。這才頓悟,對(duì)整個(gè)網(wǎng)站的結(jié)構(gòu)進(jìn)行了修改。

網(wǎng)站根目錄下放上一個(gè)入口點(diǎn)文件,讓它來(lái)對(duì)整個(gè)網(wǎng)站所有頁(yè)面進(jìn)行管理,這個(gè)時(shí)候注冊(cè)頁(yè)面變成了http://localhost/?act=register,任何頁(yè)面只是act的一個(gè)參數(shù),在得到這個(gè)參數(shù)后,再用一個(gè)switch來(lái)選擇要包含的文件內(nèi)容。在這個(gè)入口點(diǎn)文件中,還可以包含一些常量的定義,比如網(wǎng)站的絕對(duì)路徑、網(wǎng)站的地址、數(shù)據(jù)庫(kù)用戶(hù)密碼。以后我們?cè)谀_本的編寫(xiě)中,盡量使用絕對(duì)路徑而不要使用相對(duì)路徑(否則腳本如果改變位置,代碼也要變),而這個(gè)絕對(duì)路徑就來(lái)自入口點(diǎn)文件中的定義。

當(dāng)然,在安全性上,一個(gè)入口點(diǎn)文件也能隱藏后臺(tái)地址。像這樣的地址http://localhost/?act=xxx不會(huì)暴露后臺(tái)絕對(duì)路徑,甚至可以經(jīng)常更改,不用改變太多代碼。一個(gè)入口點(diǎn)文件也可以驗(yàn)證訪問(wèn)者的身份,比如一個(gè)網(wǎng)站后臺(tái),不是管理員就不允許查看任何頁(yè)面。在入口點(diǎn)文件中就可以驗(yàn)證身份,如果沒(méi)有登錄,就輸出404頁(yè)面。

有了入口點(diǎn)文件,我就把所有非入口點(diǎn)文件前面加上了這句話(huà):

<?php

if(!defined('WWW_ROOT'))

{

header("HTTP/1.1 404 Not Found");

exit;

}

?>

WWW_ROOT是我在入口點(diǎn)中定義的一個(gè)常量,如果用戶(hù)是通過(guò)這個(gè)頁(yè)面的絕對(duì)路徑訪問(wèn)(http://localhost/register.php),我就輸出404錯(cuò)誤;只有通過(guò)入口點(diǎn)訪問(wèn)(http://localhost/?act=register),才能執(zhí)行后面的代碼。

2、使用預(yù)編譯語(yǔ)句,避免sql注入

注入是早前很大的一個(gè)問(wèn)題,不過(guò)近些年因?yàn)榇蠹冶容^重視這個(gè)問(wèn)題,所以慢慢變得好了很多。

吳翰清在web白帽子里說(shuō)的很好,其實(shí)很多漏洞,像sql注入或xss,都是將“數(shù)據(jù)”和“代碼”沒(méi)有區(qū)分開(kāi)。“代碼”是程序員寫(xiě)的內(nèi)容,“數(shù)據(jù)”是用戶(hù)可以改變的內(nèi)容。如果我們寫(xiě)一個(gè)sql語(yǔ)句select * from admin where username='admin' password='xxxxx', admin和xxxxx就是數(shù)據(jù),是用戶(hù)輸入的用戶(hù)名和密碼,但如果沒(méi)有任何處理,用戶(hù)輸入的就可能是“代碼”,比如'or ''=',這樣就造成了漏洞。“代碼”是絕對(duì)不能讓用戶(hù)接觸的。

在php中,對(duì)于MySQL數(shù)據(jù)庫(kù)有兩個(gè)模塊,mysql和mysqli,mysqli的意思就是mysql improve。mysql的改進(jìn)版,這個(gè)模塊中就含有“預(yù)編譯”這個(gè)概念。像上面那個(gè)sql語(yǔ)句,改一改:select * from admin where username='?' password='?',它就不是一個(gè)sql語(yǔ)句了,但是可以通過(guò)mysqli的預(yù)編譯功能先把他編譯成stmt對(duì)象,在后期用戶(hù)輸入賬號(hào)密碼后,用stmt->bind_param將用戶(hù)輸入的“數(shù)據(jù)”綁定到這兩個(gè)問(wèn)號(hào)的位置。這樣,用戶(hù)輸入的內(nèi)容就只能是“數(shù)據(jù)”,而不可能變成“代碼”。

這兩個(gè)問(wèn)號(hào)限定了“數(shù)據(jù)”的位置,以及sql語(yǔ)句的結(jié)構(gòu)。我們可以把我們所有的數(shù)據(jù)庫(kù)操作都封裝到一個(gè)類(lèi)中,所有sql語(yǔ)句的執(zhí)行都進(jìn)行預(yù)編譯。這樣就完全避免了sql注入,這也是吳翰清最推薦的解決方案。

下面是使用mysqli的一些代碼部分(所有的判斷函數(shù)運(yùn)行成功或失敗的代碼我都省略了,但不代表不重要):

<?php

//用戶(hù)輸入的數(shù)據(jù)

$name = 'admin';

$pass = '123456';

//首先新建mysqli對(duì)象,構(gòu)造函數(shù)參數(shù)中包含了數(shù)據(jù)庫(kù)相關(guān)內(nèi)容。

$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);

//設(shè)置sql語(yǔ)句默認(rèn)編碼

$this->mysqli->set_charset("utf8");

//創(chuàng)建一個(gè)使用通配符的sql語(yǔ)句

$sql = 'SELECT user_id FROM admin WHERE username=? AND password=?;';

//編譯該語(yǔ)句,得到一個(gè)stmt對(duì)象.

$stmt = $conn->prepare($sql);

/********************之后的內(nèi)容就能重復(fù)利用,不用再次編譯*************************/

//用bind_param方法綁定數(shù)據(jù)

//大家可以看出來(lái),因?yàn)槲伊袅藘蓚€(gè)?,也就是要向其中綁定兩個(gè)數(shù)據(jù),所以第一個(gè)參數(shù)是綁定的數(shù)據(jù)的類(lèi)型(s=string,i=integer),第二個(gè)以后的參數(shù)是要綁定的數(shù)據(jù)

$stmt->bind_param('ss', $name, $pass);

//調(diào)用bind_param方法綁定結(jié)果(如果只是檢查該用戶(hù)與密碼是否存在,或只是一個(gè)DML語(yǔ)句的時(shí)候,不用綁定結(jié)果)

//這個(gè)結(jié)果就是我select到的字段,有幾個(gè)就要綁定幾個(gè)

$stmt->bind_result($user_id);

//執(zhí)行該語(yǔ)句

$stmt->execute();

//得到結(jié)果

if($stmt->fetch()){

echo '登陸成功';

//一定要注意釋放結(jié)果資源,否則后面會(huì)出錯(cuò)

$stmt->free_result();

return $user_id; //返回剛才select到的內(nèi)容

}else{echo '登錄失敗';}

?>

3、預(yù)防XSS代碼,如果不需要使用cookie就不使用

在我的網(wǎng)站中并沒(méi)有使用cookie,更因?yàn)槲覍?duì)權(quán)限限制的很死,所以對(duì)于xss來(lái)說(shuō)危險(xiǎn)性比較小。

對(duì)于xss的防御,也是一個(gè)道理,處理好“代碼”和“數(shù)據(jù)”的關(guān)系。當(dāng)然,這里的代碼指的就是JAVAscript代碼或html代碼。用戶(hù)能控制的內(nèi)容,我們一定要使用htmlspecialchars等函數(shù)來(lái)處理用戶(hù)輸入的數(shù)據(jù),并且在JavaScript中要謹(jǐn)慎把內(nèi)容輸出到頁(yè)面中。

4、限制用戶(hù)權(quán)限,預(yù)防CSRF

現(xiàn)在腳本漏洞比較火的就是越權(quán)行為,很多重要操作使用GET方式執(zhí)行,或使用POST方式執(zhí)行而沒(méi)有核實(shí)執(zhí)行者是否知情。

CSRF很多同學(xué)可能比較陌生,其實(shí)舉一個(gè)小例子就行了:

A、B都是某論壇用戶(hù),該論壇允許用戶(hù)“贊”某篇文章,用戶(hù)點(diǎn)“贊”其實(shí)是訪問(wèn)了這個(gè)頁(yè)面:http://localhost/?act=support&articleid=12。這個(gè)時(shí)候,B如果把這個(gè)URL發(fā)送給A,A在不知情的情況下打開(kāi)了它,等于說(shuō)給articleid=12的文章贊了一次。

所以該論壇換了種方式,通過(guò)POST方式來(lái)贊某篇文章。

<form action="http://localhost/?act=support" method="POST">

<input type="hidden" value="12" name="articleid">

<input type="submit" value="贊">

</form>

可以看到一個(gè)隱藏的input框里含有該文章的ID,這樣就不能通過(guò)一個(gè)URL讓A點(diǎn)擊了。但是B可以做一個(gè)“極具誘惑力”的頁(yè)面,其中某個(gè)按鈕就寫(xiě)成這樣一個(gè)表單,來(lái)誘惑A點(diǎn)擊。A一點(diǎn)擊,依舊還是贊了這篇文章。

最后,該論壇只好把表單中增加了一個(gè)驗(yàn)證碼。只有A輸入驗(yàn)證碼才能點(diǎn)贊。這樣,徹底死了B的心。

但是,你見(jiàn)過(guò)哪個(gè)論壇點(diǎn)“贊”也要輸入驗(yàn)證碼?

所以吳翰清在白帽子里也推薦了最好的方式,就是在表單中加入一個(gè)隨機(jī)字符串token(由php生成,并保存在SESSION中),如果用戶(hù)提交的這個(gè)隨機(jī)字符串和SESSION中保存的字符串一致,才能贊。

在B不知道A的隨機(jī)字符串時(shí),就不能越權(quán)操作了。

我在網(wǎng)站中也多次使用了TOKEN,不管是GET方式還是POST方式,通常就能抵御99%的CSRF估計(jì)了。

5、嚴(yán)格控制上傳文件類(lèi)型

上傳漏洞是很致命的漏洞,只要存在任意文件上傳漏洞,就能執(zhí)行任意代碼,拿到webshell。

我在上傳這部分,寫(xiě)了一個(gè)php類(lèi),通過(guò)白名單驗(yàn)證,來(lái)控制用戶(hù)上傳惡意文件。在客戶(hù)端,我通過(guò)javascript先驗(yàn)證了用戶(hù)選擇的文件的類(lèi)型,但這只是善意地提醒用戶(hù),最終驗(yàn)證部分,還是在服務(wù)端。

白名單是必要的,你如果只允許上傳圖片,就設(shè)置成array('jpg','gif','png','bmp'),當(dāng)用戶(hù)上傳來(lái)文件后,取它的文件名的后綴,用in_array驗(yàn)證是否在白名單中。

在上傳文件數(shù)組中,會(huì)有一個(gè)MIME類(lèi)型,告訴服務(wù)端上傳的文件類(lèi)型是什么,但是它是不可靠的,是可以被修改的。在很多存在上傳漏洞的網(wǎng)站中,都是只驗(yàn)證了MIME類(lèi)型,而沒(méi)有取文件名的后綴驗(yàn)證,導(dǎo)致上傳任意文件。

所以我們?cè)陬?lèi)中完全可以忽略這個(gè)MIME類(lèi)型,而只取文件名的后綴,如果在白名單中,才允許上傳。

當(dāng)然,服務(wù)器的解析漏洞也是很多上傳漏洞的突破點(diǎn),所以我們盡量把上傳的文件重命名,以“日期時(shí)間+隨機(jī)數(shù)+白名單中后綴”的方式對(duì)上傳的文件進(jìn)行重命名,避免因?yàn)榻馕雎┒炊斐扇我獯a執(zhí)行。

6、加密混淆javascript代碼,提高攻擊門(mén)檻

很多xss漏洞,都是黑客通過(guò)閱讀javascript代碼發(fā)現(xiàn)的,如果我們能把所有javascript代碼混淆以及加密,讓代碼就算解密后也是混亂的(比如把所有變量名替換成其MD5 hash值),提高閱讀的難度。

7、使用更高級(jí)的hash算法保存數(shù)據(jù)庫(kù)中重要信息

這個(gè)硬盤(pán)容量大增的時(shí)期,很多人擁有很大的彩虹表,再加上類(lèi)似于cmd5這樣的網(wǎng)站的大行其道,單純的md5已經(jīng)等同于無(wú)物,所以我們迫切的需要更高級(jí)的hash算法,來(lái)保存我們數(shù)據(jù)庫(kù)中的密碼。

所以后來(lái)出現(xiàn)了加salt的md5,比如discuz的密碼就是加了salt。其實(shí)salt就是一個(gè)密碼的“附加值”,比如A的密碼是123456,而我們?cè)O(shè)置的salt是abc,這樣保存到數(shù)據(jù)庫(kù)的可能就是md5('123456abc'),增加了破解的難度。

但是黑客只要得知了該用戶(hù)的salt也能跑md5跑出來(lái)。因?yàn)楝F(xiàn)在的計(jì)算機(jī)的計(jì)算速度已經(jīng)非常快了,一秒可以計(jì)算10億次md5值,弱一點(diǎn)的密碼分把鐘就能跑出來(lái)。

所以后來(lái)密碼學(xué)上改進(jìn)了hash,引進(jìn)了一個(gè)概念:密鑰延伸。說(shuō)簡(jiǎn)單點(diǎn)就是增加計(jì)算hash的難度(比如把密碼用md5()函數(shù)循環(huán)計(jì)算1000次),故意減慢計(jì)算hash所用的時(shí)間,以前一秒可以計(jì)算10億次,改進(jìn)后1秒只能計(jì)算100萬(wàn)次,速度慢了1000倍,這樣,所需的時(shí)間也就增加了1000倍。

那么對(duì)于我們,怎么使用一個(gè)安全的hash計(jì)算方法?大家可以翻閱emlog的源碼,可以在include目錄里面找到一個(gè)HashPaaword.php的文件,其實(shí)這就是個(gè)類(lèi),emlog用它來(lái)計(jì)算密碼的hash。

這個(gè)類(lèi)有一個(gè)特點(diǎn),每次計(jì)算出的hash值都不一樣,所以黑客不能通過(guò)彩虹表等方式破解密碼,只能用這個(gè)類(lèi)中一個(gè)checkpassword方法來(lái)返回用戶(hù)輸入密碼的正確性。而該函數(shù)又特意增加了計(jì)算hash的時(shí)間,所以黑客很難破解他們拿到的hash值。

在最新的php5.5中,這種hash算法成為了一個(gè)正式的函數(shù),以后就能使用該函數(shù)來(lái)hash我們的密碼了

8、驗(yàn)證碼安全性

驗(yàn)證碼通常是由php腳本生成的隨機(jī)字符串,通過(guò)GD庫(kù)的處理,制作成圖片。真正的驗(yàn)證碼字符串保存在SESSION中,然后把生成的圖片展示給用戶(hù)。用戶(hù)填寫(xiě)了驗(yàn)證碼提交后,在服務(wù)端上SESSION中的驗(yàn)證碼進(jìn)行比對(duì)。

由此想到了我之前犯過(guò)的一個(gè)錯(cuò)誤。驗(yàn)證碼比對(duì)完成之后,不管是正確還是錯(cuò)誤,我都沒(méi)有清理SESSION。這樣產(chǎn)生了一個(gè)問(wèn)題,一旦一個(gè)用戶(hù)第一次提交驗(yàn)證碼成功,第二次以后不再訪問(wèn)生成驗(yàn)證碼的腳本,這時(shí)候SESSION中的驗(yàn)證碼并沒(méi)有更新,也沒(méi)有刪除,導(dǎo)致驗(yàn)證碼重復(fù)使用,起不到驗(yàn)證的作用。

再就說(shuō)到了驗(yàn)證碼被識(shí)別的問(wèn)題,WordPress包括emlog的程序我經(jīng)常會(huì)借鑒,但他們所使用的驗(yàn)證碼我卻不敢恭維。很多垃圾評(píng)論都是驗(yàn)證碼被機(jī)器識(shí)別后產(chǎn)生的,所以我后來(lái)也使用了一個(gè)復(fù)雜一點(diǎn)的驗(yàn)證碼,據(jù)說(shuō)是w3c推薦使用的。

好了,我能想到的,也是在實(shí)際運(yùn)用中用到的東西也就這么多了。這也僅僅是我自己寫(xiě)代碼中積累的一些對(duì)代碼安全性的一個(gè)見(jiàn)解,如果大家還有更好的想法,可以和我交流。希望大家也能寫(xiě)出更安全的代碼。

分享到:
標(biāo)簽:php
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定