CKEditor如何防范CSRF?

时间:2018-03-27 08:33:21

标签: cookies ckeditor csrf-protection

使用CKEditor(4.9.1)时,您可能会注意到正在设置ckCsrfToken cookie。从release notes开始,这似乎在上传文件时用作CSRF保护。

我无法找到有关CKEditor如何防范CSRF攻击的任何文档。 CKEditor是否实施了Double Submit Cookie策略?

我问的原因是我们的客户想要解释这个cookie的用途,而不仅仅是HTTP。

任何指向参考文档或源代码的链接都将受到赞赏:)

1 个答案:

答案 0 :(得分:2)

TL; DR:证据显示CKEditor允许任何第三方文件上传器通过使用双提交Cookie策略来保护自己免受CSRF攻击。

现在看一下完整的故事:查看源代码,看起来CKEditor generates a CSRF token on demand并将其存储在cookie中(不能只在客户端设置的HTTP):

/**
 * Returns the CSRF token value. The value is a hash stored in `document.cookie`
 * under the `ckCsrfToken` key. The CSRF token can be used to secure the communication
 * between the web browser and the server, i.e. for the file upload feature in the editor.
 *
 * @since 4.5.6
 * @returns {String}
 */
getCsrfToken: function() {
    var token = CKEDITOR.tools.getCookie( TOKEN_COOKIE_NAME );

    if ( !token || token.length != TOKEN_LENGTH ) {
        token = generateToken( TOKEN_LENGTH );
        CKEDITOR.tools.setCookie( TOKEN_COOKIE_NAME, token );
    }

    return token;
}

然后File ToolsFile Browser插件在调用上传网址时都会提交该令牌,如in the fileUploadRequest handler所示:

// Append token preventing CSRF attacks.
$formData.append( 'ckCsrfToken', CKEDITOR.tools.getCsrfToken() );

in the appendToken method

tokenElement.setAttribute( 'value', CKEDITOR.tools.getCsrfToken() );

CKEditor控件本身不附带“文件上传器”。因此,开发人员有责任将CKEditor集成到他/她的产品中,以使用此令牌实现CSRF保护。

CKFinder - 与CKEditor集成的付费“文件上传器” - 使用CSRF令牌,looking at the release notes,似乎为CKFinder添加了此令牌:

  

CKEditor用户注意事项:为了使用更新的CKFinder(启用CSRF保护)直接在CKEditor内上传文件,还应将CKEditor更新为最新的稳定版本(2016年12月9日发布的CKEditor 4.5.6)。

最后,source code of CKFinder清楚地表明CSRF保护是使用Double Submit Cookie策略实现的(请参阅DoubleSubmitCookieTokenValidator.php):

/**
 * DoubleSubmitCookieTokenValidator constructor.
 *
 * @param string $tokenParamName
 * @param string $tokenCookieName
 * @param int    $minTokenLength
 */
public function __construct($tokenParamName = 'ckCsrfToken', $tokenCookieName = 'ckCsrfToken', $minTokenLength = 32)
{
    $this->tokenParamName = $tokenParamName;
    $this->tokenCookieName = $tokenCookieName;
    $this->minTokenLength = $minTokenLength;
}

/**
 * Checks if the request contains a valid CSRF token.
 *
 * @param Request $request
 *
 * @return bool `true` if the token is valid, `false` otherwise.
 */
public function validate(Request $request)
{
    $paramToken = trim((string) $request->get($this->tokenParamName));
    $cookieToken = trim((string) $request->cookies->get($this->tokenCookieName));

    if (strlen($paramToken) >= $this->minTokenLength && strlen($cookieToken) >= $this->minTokenLength) {
        return $paramToken === $cookieToken;
    }

    return false;
}