在wordpress中,為了增加系統(tǒng)的驗(yàn)證安全性,內(nèi)置了一些簡(jiǎn)單的驗(yàn)證,這些驗(yàn)證可以有效的防治注冊(cè)、提交等操作,如果開發(fā)者在主題開發(fā)中,對(duì)數(shù)據(jù)庫(kù)進(jìn)行了操作,一定要使用到這些函數(shù)
語法結(jié)構(gòu)
<?php wp_nonce_field($action, $name, $referer, $echo) ?> //為輸入框檢索或顯示隨機(jī)數(shù)隱藏字段
參數(shù)
$action(可選)操作名稱
$name (可選)Nonce名稱
$referer(可選)是否還應(yīng)使用wp_referer_field()函數(shù)創(chuàng)建referer隱藏表單字段,默認(rèn)值:true
$echo(可選)如果$referer參數(shù)設(shè)置為true,是顯示還是返回nonce隱藏表單字段,還是referer隱藏表單字段。默認(rèn)值:true
實(shí)例
<? php wp_nonce_field(); ?> //最簡(jiǎn)單的使用方法,省略所有參數(shù),在表單中添加內(nèi)容,安全性偏低
最好給$action和$name命名,可以較大提高WordPress安全性
<form method =“post”>
<! - 這里的一些輸入...... - >
<?php wp_nonce_field('name_of_my_action','name_of_nonce_field'); ?>
</form>
Nonce 是 WordPress 安全的一個(gè)重要組成部分,但是 Nonce 經(jīng)常會(huì)被誤解以及誤用。它們是授權(quán)一個(gè) HTTP 請(qǐng)求到您的網(wǎng)站的一個(gè)關(guān)鍵部分,用來保證你的代碼安全。
在這篇文章中,您將了解什么是 nonce,一個(gè) WordPress nonce 是什么,它們是如何能夠防御某些類型的攻擊,還有他們無法防御的攻擊類型,以及如何使用它們。
什么是Nonce
Nonce 是加密散列,用來驗(yàn)證是否是正確的人或客戶端所發(fā)送的請(qǐng)求。因?yàn)?nonce 是使用一個(gè)加密散列算法(例如 md5,sha1,sha2)和某種形式的秘密數(shù)據(jù)構(gòu)造的,一般來說不太可能創(chuàng)建一個(gè)假的 nonce。
nonce 這個(gè)單詞意思是:僅使用一次的數(shù)字。nonce 安全性的一個(gè)關(guān)鍵特性就是一次性使用。即使你攔截獲得了一個(gè)有效的 nonce,一旦它被使用了,就無法再次使用。這個(gè)使得 nonce 對(duì)于重復(fù)攻擊很有效。
就是說,WordPress nonce,并不是真正的 nonce,因?yàn)樗梢栽谀扯螘r(shí)間內(nèi)一直有效,可以通過 nonce_life
(詳見Code Reference) 這個(gè) filter 來定義它從創(chuàng)建開始的時(shí)效。這個(gè)意味著從技術(shù)上講 WordPress nonce 可以使用不止一次,但僅限這個(gè)定義的時(shí)間段里。這個(gè)是需要謹(jǐn)記在心的區(qū)別。
跨站點(diǎn)請(qǐng)求偽造
我們經(jīng)常認(rèn)為我們的 WordPress 站點(diǎn)僅僅通過填寫表單(如結(jié)賬表單,文章編輯器,用戶個(gè)人資料編輯器等等),然后點(diǎn)擊提交來接受數(shù)據(jù)。但是那個(gè)僅僅是向一個(gè)站點(diǎn)發(fā)送 HTTP 請(qǐng)求的許多方法中的一個(gè)。
一旦一個(gè)表單的結(jié)構(gòu)被摸清,然后就可以寫一個(gè)腳本來模仿向這個(gè)表單發(fā)送請(qǐng)求。利用此漏洞來進(jìn)行攻擊的一種方式就是:在另外一個(gè)站點(diǎn)放上此表單的假版本,然后提交回原站點(diǎn),來插入惡意數(shù)據(jù)。
這個(gè)就是一個(gè)跨站點(diǎn)請(qǐng)求偽造(CSRF)的攻擊例子。它很大程度上可以通過使用 nonce 來避免。即使表單保持一模一樣,然而 nonce 字段的值無法猜到。
每個(gè)發(fā)送給 WordPress 站點(diǎn)的請(qǐng)求,一個(gè)選項(xiàng)表單,一個(gè)針對(duì) admin-ajax 的請(qǐng)求,Wordpress REST API,或者其他任何可以在站外發(fā)起的請(qǐng)求,都應(yīng)該通過 nonce 來保護(hù)。
Nonce 只是整個(gè)系統(tǒng)的一部分
需要記住的是:僅驗(yàn)證一個(gè) nonce,對(duì)于確定發(fā)送的請(qǐng)求是否經(jīng)過授權(quán)是不夠的。對(duì)于任何一個(gè)請(qǐng)求,權(quán)限的檢驗(yàn)都是必要的。思考下面3個(gè)在 WordPress 插件中使用 admin-ajax 保存選項(xiàng)的例子:
<?php
add_action( 'wp_ajax_save_weibo', function(){
if( isset( $_POST[ 'weibo' ]
) ){
update_option( 'weibo', strip_tags( $_POST[ 'weibo' ]
) );
}
});
add_action( 'wp_ajax_save_weibo', function(){
if( current_user_can( 'mange_options' ) && isset( $_POST[ 'weibo' ]
) ){
update_option( 'weibo', strip_tags( $_POST[ 'weibo' ]
) );
}
});
add_action( 'wp_ajax_save_weibo', function(){
if( current_user_can( 'mange_options' ) && isset( $_POST[ 'weibo-save-nonce' ] , $_POST[ 'weibo' ] ) && wp_verify_nonce( $_POST[ 'weibo-save-nonce' ]
, 'weibo-save-nonce' ) ){
update_option( 'weibo', strip_tags( $_POST[ 'weibo' ]
) );
}
});
?>
第一個(gè)例子允許任何擁有有效 cookie 的任何角色的用戶來更新這個(gè)選項(xiàng)。如果你在 WordPress 站點(diǎn)使用這個(gè)代碼,而我注冊(cè)為一個(gè)訂閱者,我可以登錄到這個(gè)網(wǎng)站,獲得我的 cookie,然后就可以使用瀏覽器控制臺(tái)或者在我的 terminal 中使用 cURL 來修改這個(gè)選項(xiàng)。這是非常不安全的做法。
第二個(gè)例子會(huì)好一些,但是仍然不安全。這個(gè)代碼中沒有 nonce,但是它正確的檢查了當(dāng)前用戶的權(quán)限。沒有 nonce,正如我們前面講的會(huì)受到跨站點(diǎn)請(qǐng)求偽造的攻擊影響。這段代碼就是釣魚攻擊網(wǎng)站的邀請(qǐng)函啊。
第三個(gè)例子增加了一個(gè) nonce,這是正確的做法。如果我有個(gè)管理員 cookie 設(shè)置,同時(shí)我輕易被釣魚網(wǎng)站欺騙了,這時(shí)候 nonce 將會(huì)起作用,讓它通過不了,也就不會(huì)造成任何破壞。
Nonce 配合著身份驗(yàn)證一起工作,這樣就無法跳過這一個(gè)或者另一個(gè)驗(yàn)證了。
使用 Nonce
WordPress 有著一系列的函數(shù)來和 nonce 配合工作。其中兩個(gè)最重要的函數(shù)是 wp_create_nonce() 和 wp_verify_nonce。都可以為動(dòng)作執(zhí)行(action)傳入可選參數(shù)。你應(yīng)當(dāng)始終為你的請(qǐng)求設(shè)置唯一的動(dòng)作執(zhí)行(action)。這意味著你的 nonce 不可以用來重復(fù)驗(yàn)證另外一種類型的請(qǐng)求。
對(duì)于 nonce 在表單中使用,有一個(gè)助手函數(shù)(helper function)叫 wp_nonce_field(),可以用來創(chuàng)建一個(gè) nonce 隱藏字段。下面這個(gè)表單可以和上面例子配合:
<form id="weibo-form">
<label for="weibo-name">
<?php esc_html_e( 'Weibo', 'text-domain' ); ?>
</label>
<input type="text" id="weibo-name" value="<?php echo esc_attr( get_option( 'weibo', '') ); ?>" />
<?php
wp_nonce_field( 'weibo-save-nonce' );
submit_button( __( 'Save', 'text-domain' ) );
?>
</form>
<script>
jQuery( document ).ready(function($){
$( '#weibo-form' ).on( 'click', function(e){
$.post( ajaxurl, {
'weibo-save-nonce' : $( '#_wpnonce' ).val(),
weibo: $( '#weibo-name')
})
});
});
</script>
這個(gè)將會(huì)用在只有管理員可以看到的菜單頁面。因此 nonce 在被使用輸出到屏幕顯示的時(shí)候,只有管理員可以看到。在 admin-ajax 的回調(diào)函數(shù)中,nonce 驗(yàn)證和權(quán)限驗(yàn)證,結(jié)合 WordPress 對(duì)用戶 cookie 的驗(yàn)證,一起來保證安全。
在這個(gè)例子中,我們使用了 AJAX 來提交表單,但是對(duì)于同步 HTTP 請(qǐng)求,這個(gè)過程是一樣的。
現(xiàn)在就開始使用 Nonce
這就是關(guān)于 nonce 的一切了。為了提高 WordPress 網(wǎng)站的安全性,記住,無論如何都要使用 Nonce。
在我總結(jié)之前,還有另外兩個(gè)觀點(diǎn)需要說的是:
關(guān)于 Nonce 有一個(gè)重要的事情需要謹(jǐn)記在心的是,nonce 其中的一個(gè)組成部分就是當(dāng)前用戶的 ID,如果沒有登錄就是 0。這個(gè)意味著 nonce 在用戶之間不可分享。這個(gè)可能會(huì)讓人產(chǎn)生困惑,就是如果 nonce 在用戶身份驗(yàn)證之前驗(yàn)證,那么正確的 nonce 將會(huì)無效。當(dāng)一個(gè) nonce 伴隨著 WordPress REST API nonce 用來驗(yàn)證 cookie 身份驗(yàn)證被使用時(shí),這就是一個(gè)會(huì)發(fā)生的問題。
另外一個(gè)重要的事情需要記住的是,nonce 會(huì)受到 PHP 計(jì)時(shí)攻擊的影響。這就是為什么 WordPress 用戶需要故意使用低效率的函數(shù) hash_equals() 替代簡(jiǎn)單高效的字符串比較。你可能產(chǎn)生過通過生成一個(gè)期望的值然后用字符串比較來驗(yàn)證一個(gè) nonce 的念頭。然而,我建議你不要嘗試和優(yōu)化 nonce 驗(yàn)證的過程。
就這么多,僅僅簡(jiǎn)單地介紹了如何使用 nonce。我希望通過這篇文章你可以看到 nonce 是多么的簡(jiǎn)單,以及對(duì)于保證你的代碼和站點(diǎn)安全是多么的重要。