对 /autodiscover/autodiscover.xml 的请求导致 TokenMismatchException

Posted

技术标签:

【中文标题】对 /autodiscover/autodiscover.xml 的请求导致 TokenMismatchException【英文标题】:Requests to /autodiscover/autodiscover.xml causing TokenMismatchException 【发布时间】:2016-01-25 09:03:26 【问题描述】:

我有一个获得合理流量的 Laravel 应用。

为了更优雅地处理 TokenMismatchException 类型的异常(当会话生命周期到期然后用户提交表单时往往会被抛出),我更改了异常处理程序的 render() 方法,如下所示:

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)

    if ($e instanceof \Illuminate\Session\TokenMismatchException)

        return redirect($request->fullUrl())->with('error',"Sorry your session has expired please resubmit your request.");
    

    return parent::render($request, $e);

这对于普通请求来说工作得很好,它不会抛出异常,而是设置会话闪存消息并重定向回请求的页面。但是,我注意到以下请求仍会引发许多此类异常:

/autodiscover/autodiscover.xml

我知道以上内容与 Exchange 有关,因此它可能不是恶意的。

我感到困惑的是 a) 为什么这个未路由的 url 会触发 Laravel 的 CSRF 保护以及 b) 为什么我更新的处理程序没有捕获异常?

我尝试为这个 url 添加路由,并手动抛出 404,但这没有帮助。

我能做些什么来防止这些异常被抛出?

编辑 - 按要求进行堆栈跟踪:

2015-10-26 11:44:38] production.ERROR: exception 'Illuminate\Session\TokenMismatchException' in /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:53
Stack trace:
#0 [internal function]: Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#1 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#2 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(54): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#3 [internal function]: Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#4 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#5 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(62): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#6 [internal function]: Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#7 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#8 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#9 [internal function]: Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#10 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#11 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(59): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#12 [internal function]: Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#14 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(42): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#15 [internal function]: Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#16 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(124): call_user_func_array(Array, Array)
#17 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\closure(Object(Illuminate\Http\Request))
#18 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#19 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(122): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#20 /var/www/vhosts/sitedomain.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(87): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#21 /var/www/vhosts/sitedomain.com/public_html/index.php(53): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#22 main  

【问题讨论】:

能否为 url /autodiscover/autodiscover.xml 添加错误跟踪转储? @Mysteryos - 当然,我已经添加了一个示例堆栈跟踪。 错误跟踪转储没有提供信息。您如何确定该文件导致了这些错误?看起来您遇到了会话持久性问题。 没有会话问题 - 我的异常处理程序在应用程序中的实际请求上下文中正常工作。这些对 /autodiscover/autodiscover.xml 的恶意请求是唯一仍在触发异常的请求。 对文件的请求不会触发 php 错误。只有访问以您的 index.php 为根的 Web 端点,才有可能触发上述错误。 【参考方案1】:

因此,解决方案变得相对简单。似乎 Laravel 的默认行为是处理所有发布(以及可能是放置和删除...)请求,无论它们是否在路由中定义。

所以我们可以在 VerifyCsrfToken 中间件 $except 数组中为此添加一个异常:

protected $except = [
    'autodiscover/autodiscover.xml'
]

加上上面的,我的TokenMismatchException就不再抛出了。

【讨论】:

仍然很奇怪。想象一个恶意用户试图通过非GET 请求访问您服务器上不存在的文件。您的日志将充满 CSRF 错误。 @Mysteryos 我完全同意 - 当然任何对不存在的路由的请求都应该被完全忽略?不存在且不是 Laravel 路由的请求的默认行为应该是 404。 它们不会 404,因为在路由请求之前应用了全局中间件,请参阅:github.com/laravel/framework/pull/9708。希望到这个 gem:laravel.com/docs/5.1/errors#report-method 您可以排除 CSRF 错误被记录。 @Mysteryos 有用的链接,谢谢。很遗憾,排除这些异常的唯一方法是全局或通过我上面的方法。理想情况下,我只想为所有未路由的 url 排除这些 - 因为这可能表明对网站的攻击。

以上是关于对 /autodiscover/autodiscover.xml 的请求导致 TokenMismatchException的主要内容,如果未能解决你的问题,请参考以下文章

如何对List 进行排序

根据对的第二个值查找对向量的上限

算法之逆序对

10:素数对

向量对还是向量对?

逆序对与本质不同的逆序对