CKEditor 如何防止 CSRF?

How does CKEditor protects against CSRF?

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

我找不到任何关于 CKEditor 如何防止 CSRF 攻击的文档。 CKEditor 是否正在实施 Double Submit Cookie 策略?

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

任何 link 参考文档或源代码将不胜感激:)

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 Tools and the File Browser plugins submit that token when calling the upload URL, as seen 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 控件本身不附带 "file uploader"。因此,将 CKEditor 集成到 his/her 产品中的开发人员有责任使用此令牌实现 CSRF 保护。

CKFinder --the paid "file uploader" that integrates with CKEditor-- makes use of the CSRF token and, looking at the release notes,好像这个token是为CKFinder添加的:

Note for CKEditor users: In order to upload files directly inside CKEditor with updated CKFinder (with CSRF protection enabled), CKEditor should also be updated to the latest stable version (CKEditor 4.5.6 released on 9th Dec, 2016).

最后,source code of CKFinder makes it clear that the CSRF protection is implemented using the 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;
}