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
에 코드를 추가하여 사용자의 기밀 데이터를 훔칠 수 있습니다.
...
String lang = Request.Form["lang"];
WebClient client = new WebClient();
client.BaseAddress = url;
NameValueCollection myQueryStringCollection = new NameValueCollection();
myQueryStringCollection.Add("q", lang);
client.QueryString = myQueryStringCollection;
Stream data = client.OpenRead(url);
...
en&poll_id=1
같은 lang
을 제공할 가능성을 고려하지 않았기 때문에 공격자는 마음대로 poll_id
를 변경할 수 있게 됩니다.
...
String lang = request.getParameter("lang");
GetMethod get = new GetMethod("http://www.example.com");
get.setQueryString("lang=" + lang + "&poll_id=" + poll_id);
get.execute();
...
en&poll_id=1
같은 lang
을 제공할 가능성을 고려하지 않았기 때문에 공격자는 마음대로 poll_id
를 변경할 수 있게 됩니다.
<%
...
$id = $_GET["id"];
header("Location: http://www.host.com/election.php?poll_id=" . $id);
...
%>
name=alice
를 지정했지만 name=alice&
를 더 추가했으며, 첫 번째 것을 가져오는 서버에서 이것이 사용되면 alice
로 가장하여 이 사용자의 계정에 대한 추가 정보를 획득할 수 있습니다.
String arg = request.getParameter("arg");
...
Intent intent = new Intent();
...
intent.setClassName(arg);
ctx.startActivity(intent);
...
Intent
가 감지되었습니다. 암시적 내부 Intent로 인해 시스템이 내부 구성 요소에 대한 MiTM(Man-in-The-Middle: 메시지 가로채기) 공격에 노출될 수 있습니다.Intent
는 내부 구성 요소에서 정의한 대로 사용자 지정 작업을 사용합니다. 암시적 Intent는 특정 구성 요소에 대한 지식 없이도 임의의 외부 구성 요소에서 Intent 호출을 용이하게 할 수 있습니다. 이 두 가지를 결합하면 응용 프로그램이 원하는 응용 프로그램 컨텍스트 외부에서 특정 내부 사용을 위해 지정된 Intent에 액세스할 수 있습니다.Intent
를 처리하는 기능을 사용하면 심각도에 따라 Intent
에 지정된 내부 작업의 용량에 따라 정보 유출 및 서비스 거부부터 원격 코드 실행까지 다양한 MiTM(Man-in-The-Middle) 공격이 가능해집니다.Intent
를 사용합니다.
...
val imp_internal_intent_action = Intent("INTERNAL_ACTION_HERE")
startActivity(imp_internal_intent_action)
...
PendingIntent
가 감지되었습니다. 암시적 PendingIntent로 인해 서비스 거부, 개인 정보 및 시스템 정보 유출, 권한 에스컬레이션과 같은 보안 취약점이 발생할 수 있습니다.Intent
를 전달하기 위해 PendingIntent가 생성됩니다. 암시적 Intent는 일반 이름과 필터를 사용하여 실행을 결정함으로써 임의의 외부 구성 요소에서 Intent 호출을 용이하게 합니다.Intent
가 PendingIntent
로 생성되는 경우 이로 인해 Intent
가 의도한 임시 컨텍스트의 외부에서 실행되는 의도하지 않은 구성 요소로 전송되어 시스템이 서비스 거부, 개인 정보 및 시스템 정보 유출, 권한 에스컬레이션과 같은 악의적 공격에 취약해질 수 있습니다.PendingIntent
를 사용합니다.
...
val imp_intent = Intent()
val flag_mut = PendingIntent.FLAG_MUTABLE
val pi_flagmutable_impintintent = PendingIntent.getService(
this,
0,
imp_intent,
flag_mut
)
...
FLAG_MUTABLE
로 설정된 PendingIntent
가 감지되었습니다. FLAG_MUTABLE
플래그 값으로 생성된 PendingIntent는 지정되지 않은 Intent
필드가 다운스트림으로 설정될 수 있으며, 이로 인해 Intent
의 용량을 수정하고 시스템을 취약점에 노출시킬 수 있습니다.PendingIntent
의 기본 Intent
수정을 허용하면 생성 후 시스템이 공격에 노출될 수 있습니다. 이는 대개 기본 Intent
의 전체적인 기능에 따라 달라집니다. 대부분의 경우 PendingIntent
플래그를 FLAG_IMMUTABLE
로 설정하여 잠재적인 문제를 방지하는 것이 모범 사례에 해당합니다.FLAG_MUTABLE
플래그 값으로 생성된 PendingIntent
를 포함합니다.
...
val intent_flag_mut = Intent(Intent.ACTION_GTALK_SERVICE_DISCONNECTED, Uri.EMPTY, this, DownloadService::class.java)
val flag_mut = PendingIntent.FLAG_MUTABLE
val pi_flagmutable = PendingIntent.getService(
this,
0,
intent_flag_mut,
flag_mut
)
...
Intent
를 사용하여 활동을 시작하거나, 서비스를 시작하거나, 브로드캐스트를 전송하면 공격자가 내부 응용 프로그램 구성 요소를 임의로 시작하거나, 내부 구성 요소의 동작을 제어하거나, 임시 권한 부여를 통해 콘텐트 공급자의 보호되는 데이터에 간접적으로 액세스할 수 있습니다.Intent
의 추가 번들에 중첩된 임의의 Intent
를 수락합니다.startActivity
, startService
또는 sendBroadcast
를 호출하는 방법으로 임의의 Intent
를 사용하여 구성 요소를 시작합니다.Intent
를 수락하고 Intent
를 사용하여 활동을 시작합니다.
...
Intent nextIntent = (Intent) getIntent().getParcelableExtra("next-intent");
startActivity(nextIntent);
...
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>
chroot()
와 같은 작업을 수행하는 데 필요한 높은 수준의 권한은 작업을 수행한 직후 삭제해야 합니다.chroot()
등의 권한 있는 함수를 호출하려면 먼저 root
권한을 획득해야 합니다. 권한 있는 작업이 완료되자 마자 프로그램은 root
권한을 삭제하고 호출한 사용자의 권한 수준으로 돌아가야 합니다.chroot()
를 호출하여 응용 프로그램을 APP_HOME
밑의 파일 시스템의 부분 집합으로 제한합니다. 그런 다음 코드는 사용자가 지정한 파일을 열고 파일의 내용을 처리합니다.
...
chroot(APP_HOME);
chdir("/");
FILE* data = fopen(argv[1], "r+");
...
setuid()
를 호출하지 않으면 응용 프로그램이 계속 불필요한 root
권한으로 동작하게 됩니다. 악의적인 연산이 수퍼유저 권한으로 수행되기 때문에 공격자가 응용 프로그램에 대한 익스플로이트에 성공하면 권한 상승 공격이 일어날 수 있습니다. 응용 프로그램이 root
사용자가 아닌 권한 수준으로 떨어지면 피해 가능성이 대폭 줄어듭니다.
...
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();