在wordpress中,为了增加系统的验证安全性,内置了一些简单的验证,这些验证可以有效的防治注册、提交等操作,如果开发者在主题开发中,对数据库进行了操作,一定要使用到这些函数
语法结构
<?php wp_nonce_field($action, $name, $referer, $echo) ?> //为输入框检索或显示随机数隐藏字段
参数
$action(可选)操作名称
$name (可选)Nonce名称
$referer(可选)是否还应使用wp_referer_field()函数创建referer隐藏表单字段,默认值:true
$echo(可选)如果$referer参数设置为true,是显示还是返回nonce隐藏表单字段,还是referer隐藏表单字段。默认值:true
实例
<? php wp_nonce_field(); ?> //最简单的使用方法,省略所有参数,在表单中添加内容,安全性偏低
最好给$action和$name命名,可以较大提高WordPress安全性
<form method =“post”>
<! - 这里的一些输入...... - >
<?php wp_nonce_field('name_of_my_action','name_of_nonce_field'); ?>
</form>
Nonce 是 WordPress 安全的一个重要组成部分,但是 Nonce 经常会被误解以及误用。它们是授权一个 HTTP 请求到您的网站的一个关键部分,用来保证你的代码安全。
在这篇文章中,您将了解什么是 nonce,一个 WordPress nonce 是什么,它们是如何能够防御某些类型的攻击,还有他们无法防御的攻击类型,以及如何使用它们。
什么是Nonce
Nonce 是加密散列,用来验证是否是正确的人或客户端所发送的请求。因为 nonce 是使用一个加密散列算法(例如 md5,sha1,sha2)和某种形式的秘密数据构造的,一般来说不太可能创建一个假的 nonce。
nonce 这个单词意思是:仅使用一次的数字。nonce 安全性的一个关键特性就是一次性使用。即使你拦截获得了一个有效的 nonce,一旦它被使用了,就无法再次使用。这个使得 nonce 对于重复攻击很有效。
就是说,WordPress nonce,并不是真正的 nonce,因为它可以在某段时间内一直有效,可以通过 nonce_life
(详见Code Reference) 这个 filter 来定义它从创建开始的时效。这个意味着从技术上讲 WordPress nonce 可以使用不止一次,但仅限这个定义的时间段里。这个是需要谨记在心的区别。
跨站点请求伪造
我们经常认为我们的 WordPress 站点仅仅通过填写表单(如结账表单,文章编辑器,用户个人资料编辑器等等),然后点击提交来接受数据。但是那个仅仅是向一个站点发送 HTTP 请求的许多方法中的一个。
一旦一个表单的结构被摸清,然后就可以写一个脚本来模仿向这个表单发送请求。利用此漏洞来进行攻击的一种方式就是:在另外一个站点放上此表单的假版本,然后提交回原站点,来插入恶意数据。
这个就是一个跨站点请求伪造(CSRF)的攻击例子。它很大程度上可以通过使用 nonce 来避免。即使表单保持一模一样,然而 nonce 字段的值无法猜到。
每个发送给 WordPress 站点的请求,一个选项表单,一个针对 admin-ajax 的请求,Wordpress REST API,或者其他任何可以在站外发起的请求,都应该通过 nonce 来保护。
Nonce 只是整个系统的一部分
需要记住的是:仅验证一个 nonce,对于确定发送的请求是否经过授权是不够的。对于任何一个请求,权限的检验都是必要的。思考下面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 站点使用这个代码,而我注册为一个订阅者,我可以登录到这个网站,获得我的 cookie,然后就可以使用浏览器控制台或者在我的 terminal 中使用 cURL 来修改这个选项。这是非常不安全的做法。
第二个例子会好一些,但是仍然不安全。这个代码中没有 nonce,但是它正确的检查了当前用户的权限。没有 nonce,正如我们前面讲的会受到跨站点请求伪造的攻击影响。这段代码就是钓鱼攻击网站的邀请函啊。
第三个例子增加了一个 nonce,这是正确的做法。如果我有个管理员 cookie 设置,同时我轻易被钓鱼网站欺骗了,这时候 nonce 将会起作用,让它通过不了,也就不会造成任何破坏。
Nonce 配合着身份验证一起工作,这样就无法跳过这一个或者另一个验证了。
使用 Nonce
WordPress 有着一系列的函数来和 nonce 配合工作。其中两个最重要的函数是 wp_create_nonce() 和 wp_verify_nonce。都可以为动作执行(action)传入可选参数。你应当始终为你的请求设置唯一的动作执行(action)。这意味着你的 nonce 不可以用来重复验证另外一种类型的请求。
对于 nonce 在表单中使用,有一个助手函数(helper function)叫 wp_nonce_field(),可以用来创建一个 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 的回调函数中,nonce 验证和权限验证,结合 WordPress 对用户 cookie 的验证,一起来保证安全。
在这个例子中,我们使用了 AJAX 来提交表单,但是对于同步 HTTP 请求,这个过程是一样的。
现在就开始使用 Nonce
这就是关于 nonce 的一切了。为了提高 WordPress 网站的安全性,记住,无论如何都要使用 Nonce。
在我总结之前,还有另外两个观点需要说的是:
关于 Nonce 有一个重要的事情需要谨记在心的是,nonce 其中的一个组成部分就是当前用户的 ID,如果没有登录就是 0。这个意味着 nonce 在用户之间不可分享。这个可能会让人产生困惑,就是如果 nonce 在用户身份验证之前验证,那么正确的 nonce 将会无效。当一个 nonce 伴随着 WordPress REST API nonce 用来验证 cookie 身份验证被使用时,这就是一个会发生的问题。
另外一个重要的事情需要记住的是,nonce 会受到 PHP 计时攻击的影响。这就是为什么 WordPress 用户需要故意使用低效率的函数 hash_equals() 替代简单高效的字符串比较。你可能产生过通过生成一个期望的值然后用字符串比较来验证一个 nonce 的念头。然而,我建议你不要尝试和优化 nonce 验证的过程。
就这么多,仅仅简单地介绍了如何使用 nonce。我希望通过这篇文章你可以看到 nonce 是多么的简单,以及对于保证你的代码和站点安全是多么的重要。
发表评论