PHP 安全输入输出方式 「防止 XSS 注入」

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。我在开发中使用严进严出的安全保障方式:

保证安全输入(严进)

添加中间件,对所有参数进行过滤转换:

  • htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体
  • strip_tags() 函数剥去字符串中的 HTMLXML 以及 PHP 的标签
class XSSFilter
{
    public function handle($request, Closure $next)
    {
        // 配置不执行过滤转换参数项,如 env 配置: XSS_EXCEPT=article_contents,html_contents
        $param_except_string = config('const.xss_filter_param_except');
        $param_except = [];
        if (!empty($param_except_string)) {
            $param_except = explode(',', $param_except_string);
        }
        $input = $request->except($param_except);
        array_walk_recursive($input, function (&$input) {
            // $input = strip_tags($input);  // 清除标签内容
            $input = htmlspecialchars($input, ENT_NOQUOTES, 'UTF-8', false); // 过滤转换预定符号
        });
        $request->merge($input);
        return $next($request);
    }
}

使用安全输出(严出)

Laravel 安全输出方式

  • Blade 模板中使用转义输出:{{ }}
  • 直接输出时,使用 e() 函数进行过滤

Bad:

$nickname = "<img src='x' onerror='alert(0)' />测试昵称";

{!! $nickname !!}

@php 
    echo $nickname 
@endphp

Good:

$nickname = "<img src='x' onerror='alert(0)' />测试昵称";

{{ $nickname }}

@php 
    echo e($nickname); 
@endphp

等同于:

  • 使用 htmlspecialchars 进行过滤转换

Bad:

$nickname = "<img src='x' onerror='alert(0)' />测试昵称";
echo $nickname;

Good:

function p($value) {
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false);
}
$nickname = "<img src='x' onerror='alert(0)' />测试昵称";
echo p($nickname);

开启 httpOnly

开启 httpOnly 后,禁止 JavaScript 脚本直接读取该 Cookie 内容

Laravel Session

创建 Cookie 时,调用

cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)

最后一个参数 $httpOnly = true

PHP 原生 Session

如果是 PHP 原生 Session 对应 Cookie 键值默认为: PHPSESSID
需要手工修改 php.ini 配置开启 httpOnly: Session.cookie_httponly = On

本作品采用《CC 协议》,转载必须注明作者和本文链接
Sparkfly
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

如果输入<>,转义成&lt;&gt; 输出的时候还要转回来吧.

4年前 评论
Sparkfly

@lovecn 输出的时候为什么要转回来 ?&lt;&gt; 这个不是HTML实体?

4年前 评论
lovecn 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!