W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
下面,我們將會(huì)回顧常見(jiàn)的安全原則,并介紹在使用 Yii 開(kāi)發(fā)應(yīng)用程序時(shí),如何避免潛在安全威脅。
無(wú)論是開(kāi)發(fā)何種應(yīng)用程序,我們都有兩條基本的安全準(zhǔn)則:
過(guò)濾輸入的意思是,用戶輸入不應(yīng)該認(rèn)為是安全的,你需要總是驗(yàn)證你獲得的輸入值是在允許范圍內(nèi)。比如,我們假設(shè) sorting 只能指定為?title
,?created_at
?和?status
?三個(gè)值,然后,這個(gè)值是由用戶輸入提供的,那么,最好在我們接收參數(shù)的時(shí)候,檢查一下這個(gè)值是否是指定的范圍。 對(duì)于基本的 PHP 而言,上述做法類似如下:
$sortBy = $_GET['sort'];
if (!in_array($sortBy, ['title', 'created_at', 'status'])) {
throw new Exception('Invalid sort value.');
}
在 Yii 中,很大可能性,你會(huì)使用?表單校驗(yàn)器?來(lái)執(zhí)行類似的檢查。
轉(zhuǎn)義輸出的意思是,根據(jù)我們使用數(shù)據(jù)的上下文環(huán)境,數(shù)據(jù)需要被轉(zhuǎn)義。比如:在 HTML 上下文,你需要轉(zhuǎn)義?<
,>
?之類的特殊字符。在 JavaScript 或者 SQL 中,也有其他的特殊含義的字符串需要被轉(zhuǎn)義。 由于手動(dòng)的給所用的輸出轉(zhuǎn)義容易出錯(cuò),Yii 提供了大量的工具來(lái)在不同的上下文執(zhí)行轉(zhuǎn)義。
SQL 注入發(fā)生在查詢語(yǔ)句是由連接未轉(zhuǎn)義的字符串生成的場(chǎng)景,比如:
$username = $_GET['username'];
$sql = "SELECT * FROM user WHERE username = '$username'";
除了提供正確的用戶名外,攻擊者可以給你的應(yīng)用程序輸入類似 '; DROP TABLE user; --` 的語(yǔ)句。 這將會(huì)導(dǎo)致生成如下的 SQL :
SELECT * FROM user WHERE username = ''; DROP TABLE user; --'
這是一個(gè)合法的查詢語(yǔ)句,并將會(huì)執(zhí)行以空的用戶名搜索用戶操作,然后,刪除?user
?表。這極有可能導(dǎo)致網(wǎng)站出差,數(shù)據(jù)丟失。(你是否進(jìn)行了規(guī)律的數(shù)據(jù)備份?)
在 Yii 中,大部分的數(shù)據(jù)查詢是通過(guò)?Active Record?進(jìn)行的,而其是完全使用 PDO 預(yù)處理語(yǔ)句執(zhí)行 SQL 查詢的。在預(yù)處理語(yǔ)句中,上述示例中,構(gòu)造 SQL 查詢的場(chǎng)景是不可能發(fā)生的。
有時(shí),你仍需要使用?raw queries?或者?query builder。在這種情況下,你應(yīng)該使用安全的方式傳遞參數(shù)。如果數(shù)據(jù)是提供給表列的值,最好使用預(yù)處理語(yǔ)句:
// query builder
$userIDs = (new Query())
->select('id')
->from('user')
->where('status=:status', [':status' => $status])
->all();
// DAO
$userIDs = $connection
->createCommand('SELECT id FROM user where status=:status')
->bindValues([':status' => $status])
->queryColumn();
如果數(shù)據(jù)是用于指定列的名字,或者表的名字,最好的方式是只允許預(yù)定義的枚舉值。
function actionList($orderBy = null)
{
if (!in_array($orderBy, ['name', 'status'])) {
throw new BadRequestHttpException('Only name and status are allowed to order by.')
}
// ...
}
如果上述方法不行,表名或者列名應(yīng)該被轉(zhuǎn)義。 Yii 針對(duì)這種轉(zhuǎn)義提供了一個(gè)特殊的語(yǔ)法,這樣可以在所有支持的數(shù)據(jù)庫(kù)都使用一套方案。
$sql = "SELECT COUNT($column) FROM {{table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
你可以在?Quoting Table and Column Names?中獲取更多的語(yǔ)法細(xì)節(jié)。
XSS 或者跨站腳本發(fā)生在輸出 HTML 到瀏覽器時(shí),輸出內(nèi)容沒(méi)有正確的轉(zhuǎn)義。例如,如果用戶可以輸入其名稱,那么他輸入<script>alert('Hello!');</script>
?而非其名字?Alexander
,所有輸出沒(méi)有轉(zhuǎn)義直接輸出用戶名的頁(yè)面都會(huì)執(zhí)行 JavaScript 代碼?alert('Hello!');
,這會(huì)導(dǎo)致瀏覽器頁(yè)面上出現(xiàn)一個(gè)警告彈出框。就具體的站點(diǎn)而言,除了這種無(wú)意義的警告輸出外,這樣的腳本可以以你的名義發(fā)送一些消息到后臺(tái),甚至執(zhí)行一些銀行交易行為。
避免 XSS 攻擊在 Yii 中非常簡(jiǎn)單,有如下兩種一般情況:
如果你需要的是純文本,你可以如下簡(jiǎn)單的轉(zhuǎn)義:
<?= \yii\helpers\Html::encode($username) ?>
如果是 HTML ,我們可以用 HtmlPurifier 幫助類來(lái)執(zhí)行:
<?= \yii\helpers\HtmlPurifier::process($description) ?>
注意: HtmlPurifier 幫助類的處理過(guò)程較為費(fèi)時(shí),建議增加緩存:
CSRF 是跨站請(qǐng)求偽造的縮寫。這個(gè)攻擊思想源自許多應(yīng)用程序假設(shè)來(lái)自用戶的瀏覽器請(qǐng)求是由用戶自己產(chǎn)生的,而事實(shí)并非如此。
比如說(shuō):an.example.com
?站點(diǎn)有一個(gè)?/logout
?URL,當(dāng)以 GET 請(qǐng)求訪問(wèn)時(shí),登出用戶。如果它是由用戶自己操作的,那么一切都沒(méi)有問(wèn)題。但是,有一天壞人在一個(gè)用戶經(jīng)常訪問(wèn)的論壇發(fā)了一個(gè)?<img src="https://atts.w3cschool.cn/attachments/image/cimg/code>?內(nèi)容的帖子。瀏覽器無(wú)法辨別請(qǐng)求一個(gè)圖片還是一個(gè)頁(yè)面,所以,當(dāng)用戶打開(kāi)含有上述標(biāo)簽的頁(yè)面時(shí),他將會(huì)從?
an.example.com
?登出。
上面就是最原始的思想。有人可能會(huì)說(shuō),登出用戶也不是什么嚴(yán)重問(wèn)題,然而,我們發(fā)送一些 POST 數(shù)據(jù)其實(shí)也不是很麻煩的事情。
為了避免 CSRF 攻擊,你總是需要:
默認(rèn)的服務(wù)器 webroot 目錄指向包含有?index.php
?的?web
?目錄。在共享托管環(huán)境下,這樣是不可能的,這樣導(dǎo)致了所有的代碼,配置,日志都在webroot目錄。
如果是這樣,別忘了拒絕除了?web
?目錄以外的目錄的訪問(wèn)權(quán)限。如果沒(méi)法這樣做,考慮將你的應(yīng)用程序托管在其他地方。
在調(diào)試模式下, Yii 展示了大量的錯(cuò)誤信息,這樣是對(duì)開(kāi)發(fā)有用的。同樣,這些調(diào)試信息對(duì)于攻擊者而言也是方便其用于破解數(shù)據(jù)結(jié)構(gòu),配置值,以及你的部分代碼。永遠(yuǎn)不要在生產(chǎn)模式下將你的?index.php
?中的?YII_DEBUG
?設(shè)置為?true
。
你同樣也不應(yīng)該在生產(chǎn)模式下開(kāi)啟 Gii。它可以被用于獲取數(shù)據(jù)結(jié)構(gòu)信息,代碼,以及簡(jiǎn)單的用 Gii 生成的代碼覆蓋你的代碼。
調(diào)試工具欄同樣也應(yīng)該避免在生產(chǎn)環(huán)境出現(xiàn),除非非常有必要。它將會(huì)暴露所有的應(yīng)用和配置的詳情信息。如果你確定需要,反復(fù)確認(rèn)其訪問(wèn)權(quán)限限定在你自己的 IP。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: