使用CKEditor(4.9.1)时,您可能会注意到正在设置ckCsrfToken
cookie。从release notes开始,这似乎在上传文件时用作CSRF保护。
我无法找到有关CKEditor如何防范CSRF攻击的任何文档。 CKEditor是否实施了Double Submit Cookie策略?
我问的原因是我们的客户想要解释这个cookie的用途,而不仅仅是HTTP。
任何指向参考文档或源代码的链接都将受到赞赏:)
答案 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 Tools和File Browser插件在调用上传网址时都会提交该令牌,如in the fileUploadRequest
handler所示:
// Append token preventing CSRF attacks.
$formData.append( 'ckCsrfToken', CKEDITOR.tools.getCsrfToken() );
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;
}