Laravel框架 之 XSS

本文的示例代码参考xss

目录

XSS

关于XSS基础知识 可以参考

本文主要讨论应对XSS的3种常见方法

  • HTTPOnly: 禁止页面JavaScript访问带有HttpOnly属性的Cookie

  • 数据有效性: 对数据有效性做校验 例如: 邮箱 / 手机号/ 账号 / 密码是否合理(符合规则)等

  • 数据的过滤: 对特殊数据进行过滤 例如: script标签等

方法1 HTTPOnly

vim httponly.php
<?php

header("Set-Cookie: cookie1=test1;");
header("Set-Cookie: cookie2=test2;httponly", false);

?>

<script>
    alert(document.cookie);
</script>
sudo vim /etc/nginx/conf.d/httponly.conf
server {
    listen 80;
    server_name httponly.test;

    location / {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /home/saas/httponly.php;
    }
}
sudo nginx -s reload

关于Nginx的安装配置 更多参考Nginx简明教程

  • 测试
sudo sh -c "echo '127.0.0.1 httponly.test' >> /etc/hosts"

浏览器打开http://httponly.test/ 查看当前cookie

laravel-xss-01.png

此时 页面弹框只能获取到未设置HTTPOnly的Cookie

laravel-xss-02.png

方法2 数据有效性

composer create-project laravel/laravel validation --prefer-dist "5.5.*"
# cd validation
php artisan make:controller DemoController

vim app/Http/Controllers/DemoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DemoController extends Controller
{

    public function store(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email|max:255',
        ]);

        return 'ok';
    }
}
vim routes/web.php
<?php

Route::post('/validation', 'DemoController@store')->name('validation');
vim app/Http/Middleware/VerifyCsrfToken.php
<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    protected $except = [
        '/validation'
    ];
}

关于Laravel框架的CSRF 更多参考Laravel框架 之 CSRF

  • 测试
php artisan serve
curl -X POST -H "Content-type: application/json" -d '{"email":"test@test.com"}' http://localhost:8000/validation

校验成功 返回信息如下

ok
curl -X POST -H "Content-type: application/json" -d '{"email":"test"}' http://localhost:8000/validation

校验失败 返回信息如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url=http://localhost:8000" />

        <title>Redirecting to http://localhost:8000</title>
    </head>
    <body>
        Redirecting to <a href="http://localhost:8000">http://localhost:8000</a>.
    </body>
</html>
  • 优化

现在校验失败会重定向到一个页面 并且显示html

下面我们做一个优化 自己控制校验异常的处理

php artisan make:request ValidationRequest

vim app/Http/Requests/ValidationRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;

class ValidationRequest extends FormRequest
{
    public function authorize(){
        return true;
    }

    public function rules()
    {
        return [
            'email' => 'required|email|max:255',
        ];
    }

    protected function failedValidation(Validator $validator)
    {
        throw new ValidationException($validator);
    }
}
vim app/Http/Controllers/DemoController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\ValidationRequest;

class DemoController extends Controller
{
    public function store(ValidationRequest $request)
    {
        return 'ok';
    }
}
vim app/Exceptions/Handler.php
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;

class Handler extends ExceptionHandler
{
    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    public function render($request, Exception $exception)
    {
        if ($exception instanceof ValidationException) {
            $message = $exception->getMessage() ?: '您没有权限操作';
            $code = $exception->getCode() ?: 401;
            return response()->json([ 'message' => $message ], $code);
        }
        return parent::render($request, $exception);
    }
}
  • 测试
php artisan serve
curl -X POST -H "Content-type: application/json" -d '{"email":"test@test.com"}' http://localhost:8000/validation

校验成功 返回信息如下

ok
curl -X POST -H "Content-type: application/json" -d '{"email":"test"}' http://localhost:8000/validation

校验失败 返回信息如下

{"message":"The given data was invalid."}

方法3 数据的过滤

composer create-project laravel/laravel purifier --prefer-dist "5.5.*"
# cd purifier
php artisan make:controller DemoController

vim app/Http/Controllers/DemoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DemoController extends Controller
{

    public function store(Request $request)
    {
        return $request->data;
    }
}
vim routes/web.php
<?php

Route::post('/purifier', 'DemoController@store')->name('purifier');
vim app/Http/Middleware/VerifyCsrfToken.php
<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    protected $except = [
        '/purifier'
    ];
}
  • 测试
php artisan serve
curl -X POST -H "Content-type: application/json" -d '{"data":"hello<script>alert(\"data\")</script>"}' http://localhost:8000/purifier

返回信息如下

hello<script>alert("data")</script>

上述<script>标签 可能会导致注入的风险

关于Web注入更多介绍 可以参考web攻击 之 注入

这里 我们可以使用HTMLPurifier来对数据进行过滤 它运用白名单机制对HTML文本信息进行XSS过滤

关于HTMLPurifier更多介绍 可以参考官网

composer require "mews/purifier:~2.0"

php artisan vendor:publish --provider="Mews\Purifier\PurifierServiceProvider"
vim config/purifier.php
<?php

return [
    'encoding'      => 'UTF-8',
    'finalize'      => true,
    'cachePath'     => storage_path('app/purifier'),
    'cacheFileMode' => 0755,
    'settings'      => [
        'demo' => [
            'HTML.Doctype'             => 'XHTML 1.0 Transitional',
            'HTML.Allowed'             => 'div,b,strong,i,em,a[href|title],ul,ol,ol[start],li,p[style],br,span[style],img[width|height|alt|src],*[style|class],pre,hr,code,h2,h3,h4,h5,h6,blockquote,del,table,thead,tbody,tr,th,td',
            'CSS.AllowedProperties'    => 'font,font-size,font-weight,font-style,margin,width,height,font-family,text-decoration,padding-left,color,background-color,text-align',
            'AutoFormat.RemoveEmpty'   => true,
        ],
    ],
];
vim app/Http/Controllers/DemoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DemoController extends Controller
{

    public function store(Request $request)
    {
        return clean($request->data, 'demo');
    }
}
  • 测试
php artisan serve
curl -X POST -H "Content-type: application/json" -d '{"data":"hello<script>alert(\"data\")</script>"}' http://localhost:8000/purifier

返回信息如下

hello

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容