目录
概述
Web安全是一个包含许多威胁模型和反击技术的领域。从Documentum REST Services 7.3版开始,我们为用户提供了许多与Web安全相关的配置参数,这些参数有助于保护REST API中的传输数据。在本文中,我们将讨论它们是什么,以及如何配置它们。
本文介绍的安全模型包括:
- 跨站点请求伪造(CSRF)
- 跨域资源共享(CORS)
- 请求卫生处理
- HTTP严格传输安全(HSTS)
- 可缓存的HTTPS响应
- 浏览器跨站点脚本(XSS)
- 跨帧脚本(XFS)
- 响应内容嗅探
跨站点请求伪造(CSRF)
跨站点请求伪造(CSRF) 是一种攻击,它迫使最终用户在当前经过身份验证的Web应用程序上执行不需要的操作。CSRF攻击专门针对状态更改请求,而不是数据盗窃,因为攻击者无法看到伪造请求的响应。这是一个简单的场景。
- Alice通过Web浏览器登录她的银行帐户,浏览器会记住会话cookie(不注销)。
- Alice访问了另一个网站,该网站告诉她可以免费赚一些钱。
- Alice点击下面的表格,显示“赢钱!
<form action="https://bank.example.com/transfer.json" method="post">
<input type="hidden" name="payee" value="MARIA"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="Win Money!" />
</form>
- 该请求实际上被重定向到她的银行网站,并使用POST方法转移她
- 从她的账户中取出钱。
- Alice对损失的钱没有感觉,因为她没有被要求第二次登录。
在Documentum REST Services中,我们支持对某些特定的身份验证方案(如Central Authentication Services(CAS)、SAML2 Web SSO等)使用客户端令牌Cookie身份验证。Web浏览器可以记住客户端令牌cookie,直到它超时。因此,cookie保存的弱点是存在的。为了保护客户端令牌Cookie免受CSRF攻击,我们从Documentum REST 7.3开始启用CSRF防护。
使用CSRF令牌进行客户端令牌身份验证
在REST服务器运行时属性文件中,有一个参数用于打开|关闭客户端令牌cookie的CSRF保护。默认情况下,该值为true,这意味着需要CSRF令牌。
rest.security.csrf.enabled=true
启用后,客户端令牌身份验证请求必须通过请求标头或请求查询参数携带CSRF令牌。Documentum REST Services中的CSRF保护设计符合 Synchronizer Token Pattern。
下面是一个在请求中使用CSRF令牌的示例,其中 DOCUMENTUM-CSRF-TOKEN默认设置为CSRF令牌标头名称。
GET /dctm-rest/repositories/REPO1
DOCUMENTUM-CSRF-TOKEN: zMp3O7u5mOu37Z1SsiuN9he/OtA7YZlf5cqcMXt9HFA=
Host: localhost:8080
cookie: DOCUMENTUM-CLIENT-TOKEN=J9Z3J0IZHfy8ib7GB8SsxbRGTBP4UJtr49…
下面是一个在查询参数中使用CSRF令牌的请求,其中csrf-token定义为参数名称。
GET /dctm-rest/repositories/REPO1?csrf-token=zMp3O7u5mOu37Z1SsiuN9he/OtA7YZlf5cqcMXt9HFA=
Host: localhost:8080
cookie: DOCUMENTUM-CLIENT-TOKEN=J9Z3J0IZHfy8ib7GB8SsxbRGTBP4UJtr49…
配置CSRF令牌生成
CSRF令牌在客户端和服务器之间协商。Documentum REST Services支持从客户端或服务器端生成CSRF令牌。有一个服务器运行时属性来控制它。
rest.security.csrf.gen
rest.security.csrf.generation.method= server | client
从服务器端生成CSRF令牌时,初始身份验证(Basic、CAS、SAML2等)的响应会在标头中返回CSRF参数和令牌。客户端应使用这些参数进行进一步的客户端令牌身份验证。
// Client's initial sign on
GET /dctm-rest/repositories/REPO1 HTTP/1.1
Host: localhost:8080
Authorization: Basic QWRtaW5pc3RyYXRvcjpQYXNzd29yZEAxMjM=
// Server response
HTTP/1.1 200
DOCUMENTUM-CSRF-HEADER-NAME: DOCUMENTUM-CSRF-TOKEN
DOCUMENTUM-CSRF-QUERY-NAME: csrf-token
DOCUMENTUM-CSRF-TOKEN: 54msohR+0TSZbC6wrUnVUaqAOWpM2eQ7PhOEb8au+F8=
Set-Cookie: DOCUMENTUM-CLIENT-TOKEN=cblcwodoxcK_MybUbNSejQYeX7U8dgS4F9SZeM4YIjh48…
当从客户端生成CSRF令牌时,初始身份验证(Basic、CAS、SAML2等)中的请求会在标头中提供CSRF参数和令牌。Documentum REST服务器在生成客户端令牌Cookie时会采用这些参数。客户端应使用这些参数进行进一步的客户端令牌身份验证。
// Client's further request
GET /dctm-rest/repositories/REPO1 HTTP/1.1
Host: localhost:8080
Authorization: Basic QWRtaW5pc3RyYXRvcjpQYXNzd29yZEAxMjM=
DOCUMENTUM-CSRF-HEADER-NAME: {csrfHeaderName}
DOCUMENTUM-CSRF-QUERY-NAME: {csrfQueryName}
DOCUMENTUM-CSRF-TOKEN: {csrfTokenValue}
// Server response
HTTP/1.1 200
Set-Cookie: DOCUMENTUM-CLIENT-TOKEN=cblcwodoxcK_MybUbNSejQYeX7U8dgS4F9SZeM4YIjh48…
为CSRF配置HTTP方法
由于CSRF攻击通常会损害更改服务器数据的请求,因此可以在客户端令牌身份验证期间排除安全的HTTP方法(GET、OPTIONS等)对CSTF令牌的要求。Documentum REST提供了另一个服务器运行时属性来控制CSRF令牌需要哪些HTTP方法。
rest.security.csrf.http_methods= POST,PUT,DELETE
Documentum REST Services还支持用于指定令牌标头名称、查询名称和令牌长度的其他属性。有关详细信息,您可以参考《Documentum REST Services开发指南》或模板文件 rest-api-runtime.properties.template。
跨域资源共享(CORS)
通常,JavaScript客户端应该在同一源中对网站发出请求。此限制阻止了JavaScript跨域边界发出请求,并催生了各种用于发出跨域请求的黑客攻击。跨域资源共享(CORS)引入了一种标准机制,所有浏览器都可以使用该机制来实现跨域请求。这是一个简单的场景。
- Alice访问了一个网站 domain-a.acme.com
- 服务器返回一个主HTML网页,其中包含对另一个的资源访问
- 域 domain-b.acme.com
<button onclick="callOtherDomain()">
ClickMe
</button>
<script>
var invocation = new XMLHttpRequest();
var url = 'http://domain-b.acme.com';
var callOtherDomain = function() {
invocation.open('GET', url);
invocation.send();
}
</script>
- Alice在单击按钮ClickMe 时出错
失败是正常现象,因为CORS阻止了从 domain-a.acme.com 到 domain-b.acme.com 的跨域访问。Documentum REST Services提供了细粒度的CORS配置,以控制来自其他域的REST请求访问。默认情况下,跨域访问被拒绝。
发出跨域请求
大多数现代Web浏览器已经在客户端支持CORS。CORS使用HTTP标头来控制对远程资源的访问。在客户端,Web浏览器会添加一个请求标头 Origin: http://other-domain.com 与请求一起添加。服务器返回特定于CORS的标头,其中包含响应 Access-Control-Allow-Origin: http://some-domains.com,该响应表示允许向API发出请求的源域。“*”表示允许所有域。
下面是一个示例。REST服务器配置为接受具有源 http://opentext.com 的请求。如果请求不包含指定的源,服务器将返回 403 Forbidden 错误。
// A cross-origin request
GET /dctm-rest/repositories
Host: localhost:8080
Origin: http://opentext.com
// Server response
HTTP/1.1 200
Access-Control-Allow-Origin: http://opentext.com
Access-Control-Expose-Headers: Location, DOCUMENTUM-CSRF-TOKEN
Access-Control-Allow-Credentials: true
许多JavaScript客户端在执行实际的安全请求之前,使用HTTP方法OPTIONS发送CORS预检请求。该机制与此类似,只是前面有一个额外的预检请求。
// A preflight request
OPTIONS /dctm-rest/services
Host: localhost:8080
Origin: http://opentext.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Location
// Server response
HTTP/1.1 200
Access-Control-Allow-Origin: http://opentext.com
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: Location
Access-Control-Expose-Headers: Location, DOCUMENTUM-CSRF-TOKEN
Access-Control-Allow-Credentials: true
在服务器端配置CORS
如前所述,默认情况下会拒绝跨域访问。为了启用它,Documentum REST服务器提供了运行时属性,以允许对特定域或所有域进行CORS访问。默认情况下,该值为false,表示禁用CORS。有关这些参数的详细用法,请参阅《Documentum REST Services开发指南》。
rest.cors.enabled=false
rest.cors.allowed.origins=
rest.cors.allowed.methods=
rest.cors.allowed.headers= *
rest.cors.allow.credentials=true
rest.cors.exposed.headers=Location
rest.cors.max.age=3600
请求卫生处理
存储的跨站点脚本允许永久注入JavaScript代码。这是一个安全漏洞,因为此JavaScript代码可导致用户会话被盗。Documentum REST Services中的请求清理可清除用户输入,以防止此漏洞。请求清理筛选输入的两个部分:
- 输入对象元数据
- 输入HTML内容
下面是在对象元数据中编写脚本注入的示例。当存储的object_name属性值呈现到HTML页面中时,将弹出意外的警报框。
{
"name" : "document",
"type" : "dm_document",
"properties" : {
"object_name" : "The<script>alert('****')</script>Document",
}
}
在Documentum REST Services中创建文档或其他对象时,服务器可以清理元数据和HTML内容,并从文本中删除任何可疑的脚本代码。以下是上述JSON的对象元数据清理结果。
{
"name" : "document",
"type" : "dm_document",
"properties" : {
"object_name" : "TheDocument",
}
}
对于HTML内容清理,默认情况下仅清理html和pub_html格式。但是,您仍然可以通过配置运行时属性将其他格式添加到内容清理中。
在服务器端配置清理
默认情况下,清理处于关闭状态,因为它会影响性能。为了启用它,Documentum REST服务器提供了运行时属性,用于分别配置元数据和内容的清理。有关这些参数的详细用法,请参阅《Documentum REST Services开发指南》。
rest.sanitize.type.metadata=false
rest.sanitize.type.content=false
rest.sanitize.content.max.size=500000
rest.sanitize.content.default.charset=UTF-8
rest.sanitize.content.format=html,pub_html
请注意,Documentum REST Services使用 OWASP AntiSamy 库来清理文本。也可以通过创建自己的策略文件来配置清理策略。《Documentum REST Services开发指南》提供了所有详细信息。
自定义卫生处理
在使用Documentum REST SDK进行自定义REST服务开发时,您可能希望为资源模型启用清理。REST提供了一个注释com.emc.documentum.rest.binding.SanitizeConfig,它允许您在自己的资源模型上自定义清理。以下是一些示例。
// Skip sanitization despite the global configuration
@SerializableType(...)
public class MyModel {
@SerializableField
@SanitizeConfig(skipSanitize=true)
private String wontBeSanitized;
...
}
// Enforce sanitization despite the global configuration
@SerializableType(...)
public class MyModel {
@SerializableField
@SanitizeConfig(enforeceSanitize=true)
private String mustBeSanitized;
...
}
HTTP严格传输安全(HSTS)
某些网站在访问时需要HTTPS/SSL协议,但允许对客户端请求进行HTTP到HTTPS重定向。这可能会导致中间人攻击漏洞。下面是一个示例。
- Alice访问了一个网站 http://mybank.acme.com,并以明文形式显示她的凭据。
- 服务器向https://mybank.acme.com发送重定向(302)响应
- Alice带着她的凭据以加密文本的形式访问 https://mybank.acme.com。
正如你所看到的,如果一个男人在中间劫持了Alice的套接字包,他可以很容易地以明文形式获得Alice的凭据。在这种情况下,尽管主机 mybank.acme.com 加强了与HTTPS的通信协议,但它并不能保护用户不将机密信息泄露给攻击者。
HTTP严格传输安全(HSTS) 是一种Web安全机制,有助于保护网站免受协议降级攻击和cookie劫持。如果服务器需要HTTPS连接,它会在其响应中发送标头 Strict-Transport-Security:max-age=,告知客户端该时间段内的所有进一步请求都应以HTTPS发出。如果客户端支持HSTS,它会使用过期策略将此设置存储在其中。由于超时时间可能很长(例如一年),因此Web浏览器通常会将设置保存在离线存储中。
Documentum REST Services添加了服务器配置参数,以便在协议为HTTPS时启用HSTS响应标头。默认情况下,Strict-Transport-Security标头处于启用状态。有关这些参数的详细用法,请参阅《Documentum REST Services开发指南》。
rest.security.headers.hsts.disabled=false
rest.security.headers.hsts.include_sub_domains=true
rest.security.headers.hsts.max_age_in_seconds=31536000
启用HSTS后,来自REST服务器的HTTPS响应将包含 Strict-Transport-Security 标头。下面是一个示例。
GET /dctm-rest/services
Host: localhost:8443
…
// Server response
HTTP/1.1 200
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
…
可缓存的HTTPS响应
除非另有指示,否则浏览器可能会存储从Web服务器接收的内容的本地缓存副本。如果通过https传输的内容存储在本地缓存中,则将来可以由有权访问同一台计算机的其他用户检索。为了消除此漏洞,响应应包含通过标头 Cache-Control、Pragma 和 Expires 指示客户端不存储本地副本的指令。
从7.3版开始,Documentum REST Services添加了一个服务器运行时参数来控制缓存标头。默认情况下,该值为false,表示已启用通过HTTPS的缓存防护。
rest.security.headers.cache_control.disabled=false
禁用缓存时,REST服务器响应如下所示。
GET /dctm-rest/services
Host: localhost:8080
// Server response
HTTP/1.1 200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
…
浏览器跨站点脚本(XSS)
跨站点脚本(XSS) 攻击是一种注入,其中恶意脚本被注入到其他良性和受信任的网站中。当攻击者使用Web应用程序向其他最终用户发送恶意代码(通常以浏览器端脚本的形式)时,就会发生XSS攻击。
- Alice经常访问搜索网站 http:// acme.com/find?q= 进行网络搜索
- 如果搜索项没有结果,网站将返回错误“404 Not Found for
- 网址/find?q=”
- 有一天,Alice收到一封邮件,其中提供了一个指向搜索网站的隐藏链接
- URL http://acme.com/find?q= 。
- Alice单击该链接并收到一个弹出消息框,提醒xss。
- 如果这是攻击者编写的恶意脚本,则Alice的机密信息可能是
- 悄无声息地偷走了。
防止XSS攻击的一种方法是防止Web浏览器在收到潜在的恶意响应时在客户端上运行脚本。XSS筛选器是一种方法。当设置了专用响应头 X-XSS-Protection 时,客户端将对收到的响应消息进行规范化,甚至停止呈现页面。
Documentum REST Services具有用于启用XSS保护的服务器配置参数。默认情况下,该值为false,表示已启用XSS保护。有关这些参数的详细用法,请参阅《Documentum REST Services 开发指南》。
rest.security.headers.xss_protection.disabled=false
rest.security.headers.xss_protection.explicit_enable=true
rest.security.headers.xss_protection.block=true
启用XSS保护(false)后,REST响应消息会添加HTTP标头 X-XSS-Protection。
// Server response
HTTP/1.1 200
X-XSS-Protection: 1; mode=block
…
跨帧脚本(XFS)
跨框架脚本(XFS) 是一种攻击,它将恶意JavaScript与加载合法页面的iframe相结合,以试图从毫无戒心的用户那里窃取数据。这是一个简单的例子。
- Alice经常访问她的银行网站http://mybank.acme.com。
- 一名攻击者创建了一个恶意网站,并向Alice发送一封邮件,让她使用
- 隐藏链接 http://mybank.evil.com,指向页面的链接会隐藏如下所示的 iframe。
<iframe style="position:absolute;top:-9999px" src="http://mybank.acme.com/flawed-page.html"></iframe>
- Alice点击链接,她看到的一切都和 mybank.acme.com 一样。
- Alice登录并检查她的银行帐户。
- Alice的机密信息被盗。
消除框架脚本漏洞的一种方法是防止Web浏览器在<frame>、<iframe>或<object>内渲染页面。Mozilla提出了响应标头X-Frame-Options来做到这一点。
Documentum REST Services添加了服务器运行时配置参数以禁用框架脚本。默认情况下,该值为false,表示已启用帧脚本防护。
rest.security.headers.x_frame_options.disabled=false
rest.security.headers.x_frame_options.policy=DENY
启用帧脚本保护后,REST响应消息会添加标头 X-Frame-Options。
// Server response
HTTP/1.1 200
X-Frame-Options: DENY
…
响应内容嗅探
内容嗅探是检查字节流内容以尝试推断其中数据的文件格式的做法。当客户端和服务器之间没有合适的机制来检测内容MIME时,它很有用。但是,它打开了一个严重的安全漏洞,通过混淆MIME嗅探算法,可以操纵浏览器以允许攻击者执行站点操作员或用户都不希望执行的操作(例如跨站点脚本)的方式解释数据。
在Documentum REST Services中,客户端和服务器通过Accept和Content-Type标头协商内容MIME,因此在大多数情况下,不需要进行内容探查。此外,Documentum REST Services还提供了一个服务器运行时参数来停止内容探查。默认情况下为false,表示已启用内容嗅探防护。
rest.security.headers.content_type_options.disabled=false
当阻止内容探查时,来自REST服务器的响应将包含标头 X-Content- Type-Options。
// Server response
HTTP/1.1 200
X-Content-Type-Options: nosniff
…
本文最初发布于 Protecting data transfer in Documentum REST Services — OpenText - Forums
https://www.codeproject.com/Articles/5362375/Protecting-Data-Transfer-in-Documentum-REST-Servic