...
tid = request->get_form_field( 'tid' ).
CALL TRANSACTION tid USING bdcdata MODE 'N'
MESSAGES INTO messtab.
...
APPHOME
을 사용하고 그런 다음 지정된 디렉터리에서 상대 경로를 사용하여 기본 라이브러리를 로드합니다.
...
string lib = ConfigurationManager.AppSettings["APPHOME"];
Environment.ExitCode = AppDomain.CurrentDomain.ExecuteAssembly(lib);
...
APPHOME
을 LIBNAME
의 악성 버전이 들어 있는 다른 경로를 가리키도록 수정하기 때문에 공격자가 라이브러리 또는 실행 파일을 로드하고 응용 프로그램에 대한 높은 권한으로 임의의 코드를 실행할 수도 있습니다. 프로그램이 환경에서 읽은 값을 확인하지 않기 때문에, 공격자가 시스템 속성 APPHOME
의 값을 제어할 수 있는 경우 응용 프로그램을 조작하여 악성 코드를 실행하게 하고 시스템을 제어할 수 있습니다.
...
RegQueryValueEx(hkey, "APPHOME",
0, 0, (BYTE*)home, &size);
char* lib=(char*)malloc(strlen(home)+strlen(INITLIB));
if (lib) {
strcpy(lib,home);
strcat(lib,INITCMD);
LoadLibrary(lib);
}
...
INITLIB
의 악성 버전이 들어 있는 다른 경로를 지정하는 방식으로 높은 응용 프로그램 권한으로 이 라이브러리에서 코드를 실행합니다. 프로그램이 환경에서 읽은 값을 확인하지 않기 때문에 공격자가 APPHOME
의 값을 제어하게 되면 응용 프로그램이 악성 코드를 실행하게 만들 수 있습니다.liberty.dll
이라는 라이브러리를 사용합니다.
LoadLibrary("liberty.dll");
liberty.dll
l의 절대 경로를 지정하지 않습니다. 공격자가 검색 순서에서 원하는 파일보다 앞쪽에 liberty.dll
이라는 악성 라이브러리를 배치하고 웹 서버 환경이 아닌 자신의 환경에서 프로그램을 실행할 방법을 찾게 되면 응용 프로그램은 신뢰할 수 있는 라이브러리 대신 악성 라이브러리를 로드합니다. 이런 종류의 응용 프로그램은 높은 권한으로 실행되기 때문에 공격자의 liberty.dll
의 내용도 높은 권한으로 실행되고 공격자가 시스템을 완전히 장악할 수 있습니다.LoadLibrary()
가 사용하는 검색 순서 때문에 발생합니다. Windows 최신 버전까지 그래왔듯이 시스템 디렉터리보다 현재 디렉터리를 먼저 검색하면 공격자가 프로그램을 로컬로 수행할 수 있어도 이런 종류의 공격은 하찮은 것이 됩니다. 검색 순서는 운영 체제 버전에 따라 결정되고 최신 운영 체제에서 다음 레지스트리 키의 값에 따라 제어됩니다.
HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
LoadLibrary()
는 다음과 같이 동작합니다.SafeDllSearchMode
가 1인 경우 검색 순서는 다음과 같습니다.PATH
환경 변수에 나열된 디렉터리.SafeDllSearchMode
가 0인 경우 검색 순서는 다음과 같습니다.PATH
환경 변수에 나열된 디렉터리.
...
ACCEPT PROGNAME.
EXEC CICS
LINK PROGRAM(PROGNAME)
COMMAREA(COMA)
LENGTH(LENA)
DATALENGTH(LENI)
SYSID('CONX')
END-EXEC.
...
APPHOME
을 사용하여 코드가 설치되는 디렉터리를 결정한 다음 특정 디렉터리 기준 상대 경로를 사용하여 네이티브 라이브러리를 로드합니다.
...
String home = System.getProperty("APPHOME");
String lib = home + LIBNAME;
java.lang.Runtime.getRuntime().load(lib);
...
APPHOME
을 LIBNAME
의 악성 버전이 들어 있는 다른 경로를 가리키도록 수정하기 때문에 공격자가 라이브러리를 로드하고 응용 프로그램에 대한 높은 권한으로 임의의 코드를 실행할 수도 있습니다. 프로그램이 환경에서 읽은 값을 확인하지 않기 때문에, 공격자가 시스템 속성 APPHOME
의 값을 제어할 수 있는 경우 응용 프로그램을 조작하여 악성 코드를 실행하게 하고 시스템을 제어할 수 있습니다. System.loadLibrary()
를 사용하여 보통 표준 시스템 디렉터리에 있는 library.dll
이라는 기본 라이브러리에서 코드를 로드합니다.
...
System.loadLibrary("library.dll");
...
System.loadLibrary()
가 로드할 라이브러리에 대해 경로가 아닌 라이브러리 이름을 받는다는 점입니다. Java 1.4.2 API 설명서에 따르면 이 함수는 다음과 같이 동작합니다[1]:library.dll
의 악성 복사본을 배치하게 되면 응용 프로그램은 의도한 파일이 아닌 악성 복사본을 로드합니다. 응용 프로그램은 그 속성 때문에 높은 권한으로 실행됩니다. 즉, 공격자의 library.dll
의 내용이 높은 권한으로 실행되어 공격자에게 시스템의 완전한 제어권을 넘겨줄 수 있습니다.Express
의 현재 문서화되지 않은 "기능" 을 사용하여 동적으로 라이브러리 파일을 로드합니다. 그런 다음 Node.js
는 계속해서 이 라이브러리([1])가 포함된 파일 또는 디렉터리에 대한 일반 라이브러리 로드 경로를 검색합니다.
var express = require('express');
var app = express();
app.get('/', function(req, res, next) {
res.render('tutorial/' + req.params.page);
});
Express
에서 Response.render()
로 전달된 페이지는 이전에 알 수 없을 때 확장의 라이브러리를 로드합니다. 이는 잘 알려진 템플릿 엔진인 pug
라이브러리 로드를 의미하기 때문에 일반적으로 "foo.pug"와 같은 입력에 대해 문제가 되지 않습니다. 하지만 공격자가 페이지와 확장을 제어할 수 있는 경우 공격자는 Node.js
모듈 로드 경로 내의 모든 라이브러리를 로드하도록 선택할 수 있습니다. 프로그램이 URL 매개 변수에서 수신한 정보를 검증하지 않기 때문에 공격자는 응용 프로그램을 조작하여 악성 코드를 실행하게 하고 시스템을 제어할 수 있습니다.APPHOME
을 사용하여 코드가 설치되는 디렉터리를 결정한 다음 특정 디렉터리 기준 상대 경로를 사용하여 네이티브 라이브러리를 로드합니다.
...
$home = getenv("APPHOME");
$lib = $home + $LIBNAME;
dl($lib);
...
APPHOME
을 LIBNAME
의 악성 버전이 들어 있는 다른 경로를 가리키도록 수정하기 때문에 공격자가 라이브러리를 로드하고 응용 프로그램에 대한 높은 권한으로 임의의 코드를 실행할 수도 있습니다. 프로그램이 환경에서 읽은 값을 확인하지 않기 때문에, 공격자가 시스템 속성 APPHOME
의 값을 제어할 수 있는 경우 응용 프로그램을 조작하여 악성 코드를 실행하게 하고 시스템을 제어할 수 있습니다.dl()
을 사용하여 sockets.dll
이라는 이름의 라이브러리에서 코드를 로드하며, 이는 설치나 구성에 따라 다양한 위치에서 로드될 수 있습니다.
...
dl("sockets");
...
dl()
가 로드할 라이브러리에 대해 경로가 아닌 라이브러리 이름을 받는다는 점입니다.sockets.dll
의 악성 복사본을 배치하게 되면 응용 프로그램은 의도한 파일이 아닌 악성 복사본을 로드합니다. 응용 프로그램은 그 속성 때문에 높은 권한으로 실행됩니다. 즉, 공격자의 sockets.dll
의 내용이 높은 권한으로 실행되어 공격자에게 시스템의 완전한 제어권을 넘겨줄 수 있습니다.Kernel.system()
을 실행하여 보통 표준 시스템 디렉터리에 있는 program.exe
라는 실행 파일을 실행합니다.
...
system("program.exe")
...
Kernel.system()
은 셸을 통해 무언가를 실행합니다. 공격자가 환경 변수 RUBYSHELL
또는 COMSPEC
을 조작할 수 있다면 Kernel.system()
에 지정되는 명령으로 호출되는 악성 실행 파일을 가리킬 수 있습니다. 응용 프로그램은 그 속성 때문에 시스템 작업을 수행하는 데 필요한 권한으로 실행됩니다. 즉, 공격자의 program.exe
는 이 권한으로 실행되어 공격자에게 시스템의 완전한 제어권을 넘겨줄 수 있습니다.Kernel.system()
호출을 실행하기 전에 환경이 정리되지 않는다는 점입니다. 공격자가 $PATH
변수를 수정하여 program.exe
라는 악성 이진 파일을 가리키도록 하고 자신의 환경에서 프로그램을 실행하면 원하는 파일 대신 악성 이진 파일이 로드됩니다. 응용 프로그램은 그 속성 때문에 시스템 작업을 수행하는 데 필요한 권한으로 실행됩니다. 즉, 공격자의 program.exe
는 이 권한으로 실행되어 공격자에게 시스템의 완전한 제어권을 넘겨줄 수 있습니다.InvokerServlet
클래스를 사용하면 공격자가 서버에서 모든 클래스를 호출할 수 있습니다.InvokerServlet
클래스는 서버의 가상 시스템에 사용할 수 있는 모든 클래스를 호출하는 데 사용할 수 있습니다. 정규화된 클래스 이름을 추측하여 공격자가 Servlet 클래스뿐만 아니라 POJO 클래스 또는 JVM에 사용 가능한 기타 클래스를 로드할 수 있습니다.
@GetMapping("/prompt_injection")
String generation(String userInput1, ...) {
return this.clientBuilder.build().prompt()
.system(userInput1)
.user(...)
.call()
.content();
}
client = new Anthropic();
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_input = ...
response = client.messages.create(
model = "claude-3-5-sonnet-20240620",
max_tokens=2048,
system = attacker_input,
messages = [
{"role": "user", "content": "Analyze this dataset for anomalies: ..."}
]
);
...
client = OpenAI()
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_input = ...
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": attacker_input},
{"role": "user", "content": "Compose a poem that explains the concept of recursion in programming."}
]
)
@GetMapping("/prompt_injection_persistent")
String generation(String userInput1, ...) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE ...");
String userName = "";
if (rs != null) {
rs.next();
userName = rs.getString("userName");
}
return this.clientBuilder.build().prompt()
.system("Assist the user " + userName)
.user(userInput1)
.call()
.content();
}
client = new Anthropic();
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_query = ...;
attacker_name = db.qyery('SELECT name FROM user_profiles WHERE ...');
response = client.messages.create(
model = "claude-3-5-sonnet-20240620",
max_tokens=2048,
system = "Provide assistance to the user " + attacker_name,
messages = [
{"role": "user", "content": attacker_query}
]
);
...
client = OpenAI()
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_name = cursor.fetchone()['name']
attacker_query = ...
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "Provide assistance to the user " + attacker_name},
{"role": "user", "content": attacker_query}
]
)
Object.prototype
을 가리키므로 개체 프로토타입을 덮어쓸 수 있는 공격자는 보통 Object.prototype
의 정의도 덮어쓸 수 있습니다. 그러면 응용 프로그램 내의 모든 개체가 영향을 받게 됩니다.undefined
로 설정할 수 있는 경우 프로토타입이 오염되면 응용 프로그램이 올바른 개체가 아닌 프로토타입에서 속성을 잘못 읽을 수도 있습니다.lodash
의 취약한 버전을 사용하여 개체의 프로토타입을 오염시킵니다.
import * as lodash from 'lodash'
...
let clonedObject = lodash.merge({}, JSON.parse(untrustedInput));
...
{"__proto__": { "isAdmin": true}}
라면 Object.prototype
에서 isAdmin = true
가 정의됩니다.
...
let config = {}
if (isAuthorizedAsAdmin()){
config.isAdmin = true;
}
...
if (config.isAdmin) {
// do something as the admin
}
...
isAdmin
은 isAuthorizedAdmin()
이 true를 반환하는 경우에만 true로 설정되어야 합니다. 그런데 응용 프로그램이 else 조건에서 config.isAdmin = false
를 설정하지 않으므로 config.isAdmin === undefined === false
가 사용됩니다.config
의 프로토타입은 이제 isAdmin === true
로 설정되었습니다. 따라서 관리자 인증을 우회할 수 있습니다.select()
쿼리를 동적으로 생성하고 실행합니다. 또한 사용자는 결과가 정렬되는 열을 지정할 수도 있습니다. 응용 프로그램이 이미 적절하게 인증되고 이 코드 세그먼트 전에 customerID
의 값을 설정했다고 가정합니다.
...
String customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
String query = "select * from invoices where productCategory = '"
+ productCategory + "' and customerID = '"
+ customerID + "' order by '"
+ sortColumn + "' asc";
SelectResult sdbResult = sdbc.select(new SelectRequest(query));
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
및 price
에 작은따옴표 문자가 들어 있지 않은 경우에만 정확하게 동작합니다. 그러나, 공격자가 productCategory
에 대한 "Fax Machines' or productCategory = \"
" 문자열 및 sortColumn
에 대한 "\" order by 'price
" 문자열을 제공하면, 쿼리는 다음과 같습니다.
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
에 필요한 authentication을 무시할 수 있으며, 모든 고객에 대한 'Fax Machines'
와 일치하는 송장 레코드를 볼 수 있습니다.customerID
의 값을 설정했다고 가정합니다.
...
productCategory = this.getIntent().getExtras().getString("productCategory");
sortColumn = this.getIntent().getExtras().getString("sortColumn");
customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
c = invoicesDB.query(Uri.parse(invoices), columns, "productCategory = '" + productCategory + "' and customerID = '" + customerID + "'", null, null, null, "'" + sortColumn + "'asc", null);
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
를 연결하여 동적으로 생성됩니다. 그러므로 쿼리는 productCategory
및 sortColumn
가 작은 따옴표 문자를 포함하지 않은 경우에만 올바르게 작동합니다. 공격자가 productCategory
에 대한 "Fax Machines' or productCategory = \"
" 문자열 및 sortColumn
에 대한 "\" order by 'price
" 문자열을 제공하면, 쿼리는 다음과 같습니다.
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
에 필요한 authentication을 무시할 수 있으며, 모든 고객에 대한 'Fax Machines'
와 일치하는 송장 레코드를 볼 수 있습니다.
...
var authenticated = true;
...
database_connect.query('SELECT * FROM users WHERE name == ? AND password = ? LIMIT 1', userNameFromUser, passwordFromUser, function(err, results){
if (!err && results.length > 0){
authenticated = true;
}else{
authenticated = false;
}
});
if (authenticated){
//do something privileged stuff
authenticatedActions();
}else{
sendUnathenticatedMessage();
}
true
로 설정하고 확인되지 않으면 false
로 설정합니다. 하지만 콜백은 IO에 의해 차단되므로 비동기로 실행되며 if (authenticated)
확인 후에 실행될 수 있습니다. 기본값은 true이기 때문에 사용자가 실제로 인증되었는지 여부와 관계없이 if 문이 실행됩니다.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
...
public class Box{
public int area;
public static final int width = 10;
public static final Box box = new Box();
public static final int height = (int) (Math.random() * 100);
public Box(){
area = width * height;
}
...
}
...
Example 1
에서 width
가 10이므로 box.area
는 10의 배수인 임의의 정수라고 예상할 수 있습니다. 그러나 실제로 해당 값은 항상 하드코드된 0 값입니다. 컴파일 시 상수를 사용하여 선언된 정적 final 필드가 먼저 초기화된 다음 각 필드가 순서대로 실행됩니다. 즉, height
는 컴파일 시 상수가 아니므로 box
가 선언된 후에 선언되기 때문에 height
필드가 초기화되기 전에 생성자가 호출됩니다.
...
class Foo{
public static final int f = Bar.b - 1;
...
}
...
class Bar{
public static final int b = Foo.f + 1;
...
}
This example is perhaps easier to identify, but would be dependent on which class is loaded first by the JVM. In this exampleFoo.f
could be either -1 or 0, andBar.b
could be either 0 or 1.
setuid root
에서 가져온 것입니다. 이 프로그램은 권한 없는 사용자를 대신하여 특정 파일 작업을 수행하고 액세스 검사를 사용하여 현재 사용자가 사용해서는 안 되는 작업을 수행하는 데 루트 권한을 사용하지 못하도록 합니다. 이 프로그램은 파일을 열고 필요한 작업을 수행하기 전에 access()
시스템 호출을 사용하여 프로그램을 실행하는 사람이 지정된 파일에 액세스할 수 있는 권한을 가지고 있는지 확인합니다.
if (!access(file,W_OK)) {
f = fopen(file,"w+");
operate(f);
...
}
else {
fprintf(stderr,"Unable to open file %s.\n",file);
}
access()
호출은 예상대로 동작하고 프로그램을 실행하는 사용자가 파일 쓰기 권한을 가지고 있으면 0
을, 그렇지 않으면 -1을 반환합니다. 하지만 access()
및 fopen()
모두 파일 핸들이 아닌 파일 이름에 대해 동작하기 때문에 file
변수가 fopen()
에 전달될 때 access()
에 전달되었을 때와 같은 디스크상의 파일을 참조한다고 보장할 수 없습니다. 공격자가 access()
호출 후 file
을 다른 파일에 대한 심볼 링크로 교체하면 프로그램은 파일이 공격자가 수정할 수 없는 파일인 경우에도 해당 파일에 루트 권한을 사용하여 작업합니다. 공격자는 프로그램을 속여 수행할 권한이 없는 작업을 수행하게 함으로써 높은 권한을 얻는 것입니다.root
권한이 있는 프로그램에만 국한되는 것은 아닙니다. 공격자가 수행할 수 없는 작업을 수행할 수 있는 응용 프로그램이라면 모두 공격의 대상이 될 수 있습니다.
fd = creat(FILE, 0644); /* Create file */
if (fd == -1)
return;
if (chown(FILE, UID, -1) < 0) { /* Change file owner */
...
}
chown()
호출 시 작동되는 파일이 creat()
호출 시 생성되는 파일과 같다고 가정하지만 반드시 그런 것은 아닙니다. chown()
은 파일 핸들이 아닌 파일 이름에 대해 작동하므로 공격자가 자신이 소유하지 않은 파일의 링크로 파일을 대체할 수 있습니다. 그러면 공격자가 chown()
호출 시 연결된 파일의 소유권을 얻게 됩니다.CBL_CHECK_FILE_EXIST
루틴을 호출하여 파일이 존재하는지 확인합니다.
CALL "CBL_CHECK_FILE_EXIST" USING
filename
file-details
RETURNING status-code
END-CALL
IF status-code NOT = 0
MOVE 3 to access-mode
MOVE 0 to deny-mode
MOVE 0 to device
CALL "CBL_CREATE_FILE" USING
filename
access-mode
deny-mode
device
file-handle
RETURNING status-code
END-CALL
END-IF
CBL_CHECK_FILE_EXIST
호출이 예상대로 작동하고 0이 아닌 값을 반환합니다. 이는 파일이 없음을 나타냅니다. 하지만 CBL_CHECK_FILE_EXIST
및 CBL_CREATE_FILE
은 모두 파일 핸들 대신 파일 이름을 사용하여 작업하기 때문에 filename
변수가 CBL_CHECK_FILE_EXIST
에 전달되었을 때 참조하던 파일과 CBL_CREATE_FILE
에 전달될 때 참조하는 파일이 여전히 동일한 것이라는 보장이 없습니다. 공격자가 CBL_CHECK_FILE_EXIST
호출 이후에 filename
을 만들 경우, CBL_CREATE_FILE
호출은 실패하며 프로그램은 파일이 비어 있다고 믿게 됩니다. 실제로는 공격자가 제어하는 데이터가 파일 안에 들어 있습니다.root
권한이 있는 프로그램에 적용될 수 있습니다. 허용되지 않는 작업을 수행하도록 프로그램을 속이면 공격자가 승격된 권한을 얻을 수 있습니다.java.text.Format
의 parse()
및 format()
메서드에는 설계 결함이 있어서 한 사용자가 다른 사용자의 데이터를 볼 수 있습니다.java.text.Format
의 parse()
및 format()
메서드에는 race condition이 있어서 한 사용자가 다른 사용자의 데이터를 볼 수 있습니다.
public class Common {
private static SimpleDateFormat dateFormat;
...
public String format(Date date) {
return dateFormat.format(date);
}
...
final OtherClass dateFormatAccess=new OtherClass();
...
public void function_running_in_thread1(){
System.out.println("Time in thread 1 should be 12/31/69 4:00 PM, found: "+ dateFormatAccess.format(new Date(0)));
}
public void function_running_in_thread2(){
System.out.println("Time in thread 2 should be around 12/29/09 6:26 AM, found: "+ dateFormatAccess.format(new Date(System.currentTimeMillis())));
}
}
format()
구현의 race condition으로 인해 첫 번째 스레드의 데이터가 두 번째 스레드의 출력에 표시됩니다.open_basedir
구성 옵션에는 파일 접근 race conditions에 취약한 설계 결함이 있어서 공격자가 file system에서 access control 검사를 피해갈 수 있습니다.open_basedir
구성 옵션이 있는 경우, PHP 프로그램이 php.ini에 지정된 디렉터리 트리 외부의 파일에 대해 작업을 수행하는 것을 막습니다. open_basedir
옵션이 보안에 전반적으로 이득이 되지만 구현은 공격자가 특정 환경에서 해당 제한 사항을 무시할 수 있는 race condition을 겪을 수 있습니다[2]. 검사 시점/사용 시점(TOCTOU) race condition은 PHP가 접근 권한 검사를 수행하는 시점과 파일을 여는 시점 사이에 존재합니다. 다른 언어의 file system race condition과 마찬가지로 이 취약점을 사용하면 공격자가 access control 검사를 통과한 파일에 대한 심볼릭 링크를 테스트에 실패한 다른 심볼릭 링크로 바꿔 보호된 파일에 대한 접근 권한을 얻을 수 있습니다.Windows.Storage.ApplicationData
클래스의 RoamingFolder
또는 RoamingSettings
속성을 사용하고 있습니다.RoamingFolder
및 RoamingSettings
속성은 로밍 응용 프로그램 데이터 저장소에서 컨테이너를 가져옵니다. 이 컨테이너는 2개 이상의 장치에서 데이터를 공유하는 데 사용할 수 있습니다. 개발자는 로밍 앱 데이터 저장소에 저장된 개체를 쓰고 읽음으로써 손상될 위험을 높입니다. 여기에는 로밍 앱 데이터 저장소를 통해 해당 개체를 공유하는 데이터, 응용 프로그램 및 시스템의 기밀성, 무결성 및 가용성이 포함됩니다.free()
함수를 두 번 호출하면 buffer overflow가 발생할 수 있습니다 프로그램이 같은 인수로 free()
함수를 두 번 호출하면 프로그램의 메모리 관리 데이터 구조가 손상됩니다. 이 손상으로 인해 프로그램이 손상되거나 경우에 따라 이후에 있을 두 번의 malloc()
호출이 같은 포인터를 반환하기도 합니다. malloc()
함수가 같은 값을 두 번 반환하고 나중에 프로그램이 이 중복 할당된 메모리에 작성되는 데이터에 대한 제어권을 공격자에게 넘겨주면 프로그램은 buffer overflow 공격에 취약해집니다.
void sh(int dummy) {
...
free(global2);
free(global1);
...
}
int main(int argc,char* argv[]) {
...
signal(SIGHUP,sh);
signal(SIGTERM,sh);
...
}
public class GuestBook extends HttpServlet {
String name;
protected void doPost (HttpServletRequest req, HttpServletResponse res) {
name = req.getParameter("name");
...
out.println(name + ", thanks for visiting!");
}
}
name
에 "Dick
" 할당name
에 "Jane
" 할당Jane, thanks for visiting!
"Jane, thanks for visiting!
"
public class ConnectionManager {
private static Connection conn = initDbConn();
...
}
dangerouslySetInnerHTML
속성이 코드에서 불필요하게 HTML을 설정합니다.dangerouslySetInnerHTML
속성은 브라우저 DOM에서 innerHTML을 사용하는 대신 사용할 수 있습니다. 이 속성을 사용할 때 발생 가능한 위험을 파악할 수 있도록 API 이름이 바뀌었습니다. 일반적으로는 코드에서 HTML을 설정하면 위험합니다. 사용자가 의도치 않게 Cross-Site Scripting(XSS) 공격에 노출되기 쉽기 때문입니다.dangerouslySetInnerHTML
속성으로 설정합니다.
function MyComponent(data) {
return (
<div
dangerouslySetInnerHTML={{__html: data.innerHTML}}
/>
);
}