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