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

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容