이 섹션에는 소스 코드 외부에 있지만 제작 중인 제품의 보안에는 여전히 중요한 내용이 모두 포함되어 있습니다. 이 섹션에서 다루는 문제들은 소스 코드와 직접적으로 관련이 없기 때문에 나머지 섹션과 분리했습니다.
https_redirect
를 false
로 설정하여 클라이언트가 통신에 HTTP를 사용하도록 허용합니다.
resource "google_compute_url_map" "urlmap" {
...
default_url_redirect {
...
https_redirect = false
...
}
...
}
rsasha1
으로 DNSSEC를 활성화하는 Terraform 구성을 보여줍니다.
resource "google_dns_managed_zone" "zone-demo" {
...
dnssec_config {
default_key_specs {
algorithm = "rsasha1"
...
}
}
...
}
networking_mode
를 ROUTES
로 설정하여 VPC 네이티브 클러스터를 활성화하지 않습니다.
resource "google_container_cluster" "cluster_demo" {
...
networking_mode = "ROUTES"
..
}
X-XSS-Protection
을 1; mode=block
으로 설정하면 이전 버전의 브라우저가 Cross-Site Scripting 취약점에 노출됩니다.X-XSS-Protection
은 다른 브라우저에 채택되어 Microsoft에서 도입한 HTTP 헤더입니다. 이는 Cross-Site Scripting
공격이 성공하는 것을 중지하도록 돕기 위해 도입되었지만 의도치 않게 안전한 웹 사이트를 취약하게 만드는 취약점을 야기합니다[1]. 이 때문에 이 헤더는 이전 버전의 Internet Explorer에서 사용해서는 안 되며 0
으로 설정하여 비활성화해야 합니다.Express
응용 프로그램에서 Helmet
미들웨어를 잘못 구성합니다.
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
라는 HTTP 헤더를 사용해야 합니다.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 헤더를 사용해야 합니다.
<http auto-config="true">
...
<headers>
...
<content-type-options disabled="true"/>
</headers>
</http>
X-Content-Type-Options
를 nosniff
로 설정하거나 이 보안 헤더를 명시적으로 비활성화하지 않습니다.X-Content-Type-Options: nosniff
라는 HTTP 헤더를 사용해야 합니다.X-Content-Type-Options
를 nosniff
로 설정하거나 이 보안 헤더를 명시적으로 비활성화하지 않습니다.X-Content-Type-Options: nosniff
라는 HTTP 헤더를 사용해야 합니다.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));
}
pwd
의 값을 덮어쓴 후 버퍼를 사용하지 않기 때문에 memset()
호출은 불필요한 저장 공간으로 간주되어 삭제됩니다[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
보다 작습니다. 그러나 포인터에 대한 산술 overflow는 정의되지 않은 동작이므로 일부 컴파일러는 buf + len >= buf
를 가정하여 랩 확인을 최적화합니다. 이와 같이 최적화하면 이 블록 뒤에 오는 코드가 buffer overflow에 취약해질 수 있습니다.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
파일의 항목은 2개의 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/*
URL 패턴은 2개의 서로 다른 서블릿 매핑에 사용됩니다.
<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>