本节包括的所有内容均与源代码无关,但对所创建产品的安全性仍然至关重要。因为本节涉及的问题与源代码没有直接关系,所以我们将它与其他章节分开。
https_redirect
设置为 false
,允许客户端使用 HTTP 进行通信。
resource "google_compute_url_map" "urlmap" {
...
default_url_redirect {
...
https_redirect = false
...
}
...
}
rsasha1
启用 DNSSEC。
resource "google_dns_managed_zone" "zone-demo" {
...
dnssec_config {
default_key_specs {
algorithm = "rsasha1"
...
}
}
...
}
networking_mode
设置为 ROUTES
,不启用 VPC-native 群集。
resource "google_container_cluster" "cluster_demo" {
...
networking_mode = "ROUTES"
..
}
X-XSS-Protection
设置为 1; mode=block
会造成在旧版浏览器中产生跨站点脚本缺陷。X-XSS-Protection
是 Microsoft 推出的 HTTP 标头,自推出以来,已被许多其他浏览器采用。该标头旨在帮助阻止 Cross-Site Scripting
攻击成功,但会无意中导致产生缺陷,使得安全的网站易受攻击[1]。由于这个原因,不应将该标头用于旧版 Internet Explorer,应将其设置为 0
以禁用。Express
应用程序中错误地配置 Helmet
中间件,从而为所有 Internet Explorer 版本启用此标头:
var express = require('express');
var app = express();
var helmet = require('helmet');
...
app.use(helmet.xssFilter({ setOnOldIE: true}));
...
Application_BeginRequest
方法为空,或不包含用于将 X-Content-Type-Options
设置为 nosniff
的函数调用,或尝试删除该标头。X-Content-Type-Options: nosniff
。X-Content-Type-Options
设置为 nosniff
。X-Content-Type-Options: nosniff
。net.http.DetectContentType()
来确定响应 Content-Type:
...
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
content_type := DetectContentType(body)
...
X-Content-Type-Options
设置为 nosniff
,也不会明确禁用此安全标头。X-Content-Type-Options: nosniff
。
<http auto-config="true">
...
<headers>
...
<content-type-options disabled="true"/>
</headers>
</http>
X-Content-Type-Options
设置为 nosniff
,也不会明确禁用此安全标头。X-Content-Type-Options: nosniff
。X-Content-Type-Options
设置为 nosniff
,也不会显式禁用此安全标头。X-Content-Type-Options: nosniff
。memset()
来擦除内存中的密码。
void GetData(char *MFAddr) {
char pwd[64];
if (GetPasswordFromUser(pwd, sizeof(pwd))) {
if (ConnectToMainframe(MFAddr, pwd)) {
// Interaction with mainframe
}
}
memset(pwd, 0, sizeof(pwd));
}
memset()
的调用会被当作一个死存储清除,因为 pwd
缓冲区在其数值被覆盖之后便不会再次使用了 [2]。因为缓冲区 pwd
包含一个敏感值,所以如果数据长期驻留在内存中,应用程序会很容易受到攻击。如果攻击者能够访问正确的内存区域,那么他们就能使用复原后的密码来获取系统的控制权。memset()
调用解析为一段 dead code,这是因为随后的操作不会再使用被写入的内存,然而显而易见的是这样做会引发安全问题。这里的问题是,很多编译器,实际上是很多编程语言在努力提高效率的同时没有考虑这个及其他安全问题。
char *buf;
int len;
...
len = 1<<30;
if (buf+len < buf) //wrap check
[handle overflow]
buf + len
大于 2^32
,因此最终值小于 buf
。但是由于指针上的运算溢出是未定义行为,一些编译器将假定 buf + len >= buf
并优化封装检查。由于该优化,后面的代码可能容易受缓冲区溢出的攻击。static files
应用程序的 serve
视图,而该应用程序不应该部署在生产环境中。从 Django 文档来看:static files
工具主要用于帮助在生产环境中成功部署静态文件。这通常意味着需要一台独立、专用的静态文件服务器,如果在本地开发这会是很大一笔费用。因此,staticfiles 应用程序附带了一个快速更新的辅助视图,可用来在开发过程中本地提供文件。DEBUG
为 True
时才有效。admin
应用程序部署在了可预测的 URL 中:
from django.conf.urls import patterns
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
...
url(r'^admin/', include(admin.site.urls)),
...
<Realm className="org.apache.catalina.realm.JAASRealm"
appName="SRN"
userClassNames="com.srn.security.UserPrincipal"
roleClassNames="com.srn.security.RolePrincipal"/>
Realm
标签可采用一个名为 debug
的可选属性,用来指示日志级别。此数值越大,日志消息越详细。如果此调试级别设置得过高,Tomcat 会将所有用户名和密码以明文形式写入日志文件中。Tomcat JAASRealm
的相关调试消息的临界值为 3(3 或更大表示不合适,2 或更小表示合适),但该临界值会因 Tomcat 提供的 Realm 类型不同而有所不同。http://host/page.jsp%00
或 http://host/page.js%2570
。更糟糕的是,如果应用程序允许用户上传任意文件,攻击者可能会利用这项机制以 JSP 的形式上传恶意代码,并请求上传的页面在服务器上执行恶意代码。
<security-constraint>
<web-resource-collection>
<web-resource-name>JSP Access for Everyone!</web-resource-name>
<description>Allow any user/role access to JSP</description>
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
web.xml
文件中的条目定义了两个 admin
角色。
<security-constraint>
<web-resource-collection>
<web-resource-name>AdminPage</web-resource-name>
<description>Admin only pages</description>
<url-pattern>/auth/noaccess/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>Administrators only</description>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
...
<security-role>
<description>Administrator</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Non-Administrator</description>
<role-name>admin</role-name>
</security-role>
/servletA/*
。
<servlet-mapping>
<servlet-name>ServletA</servlet-name>
<url-pattern>/servletA/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletB</servlet-name>
<url-pattern>/servletA/*</url-pattern>
</servlet-mapping>