随机数是“使用一次的数字”,用于帮助保护 URL 和表单免受某些类型的滥用、恶意或其他形式的滥用。
从技术上讲,WordPress随机数并不是严格的数字;它们是由数字和字母组成的哈希值。它们也只使用一次:它们的“生命周期”有限,之后它们会过期。在该时间段内,将在给定上下文中为给定用户生成相同的随机数。该操作的随机数将保持不变,直到该随机数生命周期完成。
WordPress的安全令牌被称为“nonces”(尽管与真正的nonces存在上述差异),因为它们与nonces具有大致相同的目的。它们有助于防止多种类型的攻击,包括 CSRF,但不能防止重放攻击,因为它们没有被检查为一次性使用。绝不应依赖随机数进行身份验证、授权或访问控制。使用 保护函数,并始终假设随机数可能会受到损害。current_user_can()
为什么要使用随机数?
有关为什么使用随机数的示例,请考虑管理屏幕可能会生成这样的 URL,该 URL 会丢弃第 123 号帖子。
http://example.com/wp-admin/post.php?post=123&action=trash
当您访问该URL时,WordPress将验证您的身份验证cookie信息,如果您被允许删除该帖子,将继续删除它。攻击者可以做的是让您的浏览器在您不知情的情况下转到该 URL。例如,攻击者可以在第三方页面上制作伪装链接,如下所示:
<img src="http://example.com/wp-admin/post.php?post=123&action=trash" />
这将触发您的浏览器向WordPress发出请求,浏览器将自动附加您的身份验证cookie,WordPress会将其视为有效请求。
添加随机数可以防止这种情况。例如,当使用随机数时,WordPress为用户生成的URL如下所示:
http://example.com/wp-admin/post.php?post=123&action=trash&_wpnonce=b192fc4204
如果有人试图在没有WordPress生成并提供给用户的正确随机数的情况下丢弃123号帖子,WordPress将向浏览器发送“403禁止”响应。
创建随机数
您可以创建一个随机数并将其添加到 URL 中的查询字符串中,可以将其添加到表单的隐藏字段中,也可以以其他方式使用它。
对于要在 AJAX 请求中使用的随机数,通常将随机数添加到隐藏字段中,JavaScript 代码可以从中获取它。
请注意,随机数对于当前用户的会话是唯一的,因此如果用户异步登录或注销,页面上的任何随机数将不再有效。
为访客(非登录用户)自定义随机数
默认情况下,WordPress核心为来宾生成相同的随机数,因为它们具有相同的用户ID(值)。也就是说,它不会阻止客人受到 CSRF 攻击。要增强关键操作的安全性方面,您可以为来宾开发会话机制,并挂接到nonce_user_logged_out过滤器,以便将用户 ID 值替换为会话机制中的另一个随机 ID。00
向 URL 添加随机数
若要将随机数添加到 URL,请调用wp_nonce_url()指定裸 URL 和表示操作的字符串。
$complete_url = wp_nonce_url( $bare_url, 'trash-post_'.$post->ID );
为了获得最大的保护,请确保表示操作的字符串尽可能具体。
默认情况下, wp_nonce_url()会添加一个名为 _wpnonce的字段。您可以在函数调用中指定其他名称。
$complete_url = wp_nonce_url( $bare_url, 'trash-post_'.$post->ID, 'my_nonce' );
向窗体添加随机数
若要向窗体添加随机数,请调用指定表示操作的字符串。默认情况下,会生成两个隐藏字段,一个字段的值为 nonce,另一个字段的值为当前 URL(引荐来源网址),并回显结果。
wp_nonce_field( 'delete-comment_'.$comment_id );
可能会回显如下内容:
<input type="hidden" id="_wpnonce" name="_wpnonce" value="796c7766b1" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />
为了获得最大的保护,请确保表示操作的字符串尽可能具体。
您可以为 nonce 字段指定不同的名称,可以指定不需要反向链接字段,也可以指定希望返回结果而不回显。
创建以其他方式使用的随机数
若要创建以其他方式使用的随机数,请调用指定表示操作的字符串。例如:wp_create_nonce()
$nonce = wp_create_nonce( 'my-action_'.$post->ID );
这只返回随机数本身。例如:295a686963
为了获得最大的保护,请确保表示操作的字符串尽可能具体。
验证随机数
您可以验证在 URL、管理屏幕中的表单、AJAX 请求或其他上下文中传递的随机数。
验证从管理屏幕传递的随机数 若要验证在管理屏幕
中的 URL 或表单中传递的随机数,请调用check_admin_referer()指定表示操作的字符串。
例如:
check_admin_referer( 'delete-comment_'.$comment_id );
此调用检查随机数和引用,如果检查失败,它将执行正常操作(终止脚本执行并显示“403 禁止”响应和错误消息)。
如果在创建随机数时未使用默认字段名称 (),请指定字段名称。_wpnonce
例如:
check_admin_referer( 'delete-comment_'.$comment_id, 'my_nonce' );
验证在 AJAX 请求中传递的随机数
要验证在 AJAX 请求中传递的随机数,请调用 check_ajax_referer() 指定表示操作的字符串。例如:
check_ajax_referer( 'process-comment' );
此调用检查随机数(但不检查引用),如果检查失败,则默认情况下它会终止脚本执行。
如果在创建随机数时未使用默认字段名称(_wpnonce 或 _ajax_nonce)之一,或者如果要执行其他操作而不是终止执行check_ajax_referer(),则可以指定其他参数。
验证在其他上下文中传递的随机数 若要验证在其他上下文中传递的随机数,请调用wp_verify_nonce()指定随机数和表示操作的字符串。
例如:
wp_verify_nonce( $_REQUEST['my_nonce'], 'process-comment'.$comment_id );
如果结果为 false,请不要继续处理请求。相反,请采取一些适当的操作。通常的操作是调用wp_nonce_ays() ,这会向浏览器发送“403 禁止访问”响应。
修改随机数系统
您可以通过添加各种操作和过滤器来修改随机数系统。
修改随机数生存期
默认情况下,随机数的生存期为一天。之后,即使随机数与操作字符串匹配,它也不再有效。若要更改生存期,请添加一个nonce_life筛选器,以秒为单位指定生存期。
例如,要将生存期更改为 4 小时:
add_filter( 'nonce_life', function () { return 4 * HOUR_IN_SECONDS; } );
执行其他验证
要在发现随机数和反向链接有效时执行其他验证,请添加check_admin_referrer()操作。
例如:
function wporg_additional_check ( $action, $result ) {
...
}
add_action( 'check_admin_referer', 'wporg_additional_check', 10, 2 );
以相同的方式添加check_ajax_referer()操作。check_ajax_referer
更改错误消息
您可以使用翻译系统更改随机数无效时发送的错误消息。例如:
function my_nonce_message ($translation) {
if ($translation === 'Are you sure you want to do this?') {
return 'No! No! No!';
}
return $translation;
}
add_filter('gettext', 'my_nonce_message');
其他信息
本节包含有关WordPress中随机数系统的其他信息,这些信息可能偶尔有用。
随机数寿命
请注意,就像WordPress随机数不是“使用一次的数字”一样,随机数寿命也不是真正的随机数寿命。WordPress使用具有两个即时报价(生命周期的一半)的系统,并验证当前即时报价和最后一个即时报价的随机数。在默认设置(24 小时生命周期)中,这意味着随机数中的时间信息与自 Unix 纪元以来经过的 12 小时时间段有关。这意味着在中午和午夜之间制作的随机数将具有有效期,直到第二天中午。因此,实际寿命在 12 到 24 小时之间变化。
当随机数有效时,验证随机数的函数返回当前即时报价编号 1 或 2。例如,您可以使用此信息刷新处于第二个时钟周期的随机数,以便它们不会过期。
随机数安全性
如果您正确安装了WordPress,则使用您网站独有的密钥和盐生成随机数。 并在您的文件中定义,并且该文件包含提供更多信息的注释。NONCE_KEYNONCE_SALTwp-config.php
绝不应依赖随机数进行身份验证或授权,或用于访问控制。使用 保护您的函数,始终假设 Nonces 可能会受到损害。current_user_can()
更换随机数系统
组成nonce系统的一些功能是可插拔的,因此您可以通过提供自己的功能来替换它们。
若要更改验证管理员请求或 AJAX 请求的方式,可以替换 check_admin_referrer()或 check_ajax_referrer(),或同时替换两者。
要将随机数系统替换为其他随机数系统,可以替换wp_create_nonce(),wp_verify_nonce() 和 wp_nonce_tick()。
nonce相关函数:
wp_nonce_ays(), wp_nonce_field(), wp_nonce_url(), wp_verify_nonce(), wp_create_nonce(), check_admin_referer(), check_ajax_referer(), wp_referer_field()
Nonce hooks: nonce_life, nonce_user_logged_out, explain_nonce_(verb)-(noun), check_admin_referer