일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 게임개발
- ret2libc
- gas
- pdlc
- 운영체제
- frequency-domain spectrum analysis
- DSP
- dirty cow
- 메카님
- Race condition
- DP
- linear difference equation
- 유스케이스
- Double free
- 유니티
- Rr
- AINCAA
- MAC
- CTF
- 게임 개발
- MLFQ
- 언리얼 엔진
- Security
- sampling theory
- ability task
- Unreal Engine
- stride
- 언리얼엔진
- TSet
- dtft
- Today
- Total
다양한 기록
Race Condition Problem 본문
여러 스레드, 프로세스가 공유자원을 업데이트할 때 문제가 발생 (읽기만 하면 그럴 일 없음)
프로세스나 스레드의 실행 순서에 의존적인 결과
ex. 데이터베이스
해결하기 위해 mutex 락, 언락
이런 부분이 어떻게 공격으로 연결되는가 ..
#include <stdio.h>
#include <unistd.h>
void main(void)
{
int pid;
printf("PID = %d, in BEGIN printf\n", getpid());
pid = fork();
if( pid == 0 )
{
for( int k = 0; k < 25; ++k )
{
usleep(50000);
printf("PID=%d : Child printf *****\n", getpid());
fflush(stdout);
}
}
else if( pid > 0 )
{
for( int n = 0; n < 25; ++n )
{
printf("PID=%d : Parent printf\n", getpid());
fflush(stdout);
usleep(50000);
}
}
else
{
printf("fork() error\n");
}
printf("PID = %d, in END printf\n", getpid());
}
예시 코드
슬립 시 자동 문맥 교환 (usleep이니 마이크로 단위)
아무튼 출력 결과가 다르게 나옴(순서)
여기서 공유 자원: 모니터
완전히 별개의 프로세스여도 이렇게 될 수 있음
#include <stdio.h>
#include <pthread.h>
void *printHello(void *arg)
{
printf("%s\n", (char*)arg);
}
void main()
{
pthread_t p1, p2;
printf("main: begin\n");
pthread_create(&p1, NULL, printHello, "p1");
pthread_create(&p2, NULL, printHello, "p2");
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("main: end\n");
}
p1이랑 p2가 표준 출력을 두고 경쟁 .. 최종 출력 형태가 매번 달라짐
#include <stdio.h>
#include <pthread.h>
static volatile int counter = 0;
void mythread(void *arg)
{
printf("%s: begin\n", (char*)arg);
int i;
for(i = 0; i < 1e7; ++i)
{
++counter;
}
printf("%s: done\n", (char*)arg);
}
int main(int argc, char *argv[])
{
pthread_t p1, p2;
printf("main: begin (counter = %d)\n", counter);
pthread_create(&p1, NULL, mythread, "A");
pthread_create(&p2, NULL, mythread, "B");
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("main: done, counter: %d\n", counter);
return 0;
}
결과: 매번 다름
count++
movl count, %eax
incl %eax
movl %eax, count
count++ 이라는 명령은 위와 같이 세 개의 명령으로 구성
만약 두 개의 스레드가 있을 때, 마지막 movl이 실행되기 전에 컨텍스트 스위칭되어 다른 스레드에서 값을 변경하면 문제 발생
* 운영체제 카테고리의 Concurrency 부분에 더 자세히 나옴
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
for(i = 0; i < 1e7; ++i)
{
pthread_mutex_lock(&lock);
++counter;
pthread_mutex_unlock(&lock);
}
printf("%s: done\n", (char*)arg);
}
락 걸면 해결
Race Condition Vulnerability
//Code for P1
...
balance = balance + amount;
...
movl balance, %eax
movl amount, %ebx
add %ebx, %eax
movl %eax, balance
//Code for P2
...
balance = balance - amount;
...
movl balance, %eax
movl amount, %ebx
sub %ebx, %eax
movl %eax, balance
P1은 입금, P2는 인출
가정
초기 balance = 2000
amount = 500
P1 P2
movl balance, %eax
movl amount, %ebx
movl balance, %eax
movl amount, %ebx
sub %ebx, %eax
movl %eax, balance
add %ebx, %eax
movl %eax, balance
실행이 이렇게 되면?
sub됐던 거 무시되고 balance는 2500이 됨
예시2
account A($500), account B($0)
A -> B 500 송금 .. 스레드 두개
Thread1 | Thread2 | A + B balance |
Check account A balance($500) | 500 | |
Check account A balance($500) | 500 | |
Add $500 to account B | 1000 (A 500, B 500) | |
Add $500 to account B | 1500 (A 500, B 1000) | |
Deduct $500 from account A | 1000 (A 0, B 1000) | |
Deduct $500 from account A | 1000 (A 0, B 1000), 음수는 안될 것 | |
1000 (A 0, B 1000) |
트랜잭션 안되니까 총 balance가 1000으로 불어버림
Case Study: Unlimited Starbucks Coffee
기프트 카드 합치는 게 가능한데 레이스 컨디션 문제
Thread1 | Thread2 | A + B balance |
Check card A balance($5) | 5 | |
Check card A balance($5) | 5 | |
Add $5 to card B | 10 (A 5, B 5) | |
Add $5 to card B | 15 (A 5, B 10) | |
Deduct $5 from card A | 10 (A 0, B 10) | |
Deduct $5 from card A | 10 (A 0, B 10), 음수는 안될 것 | |
10 (A 0, B 10) |
위의 계좌 문제랑 사실상 같은 문제임
function withdraw($amount)
{
$balance = getBalance();
if( $amount <= $balance ) // check
{
$balance = $balance - $amount; // use
echo "You have withdrawn: $amount";
saveBalance($balance);
}
else
{
echo "Insufficient funds.";
}
}
check랑 use 사이에 공격이 들어오면 문제가 발생할 수 있음
=> ToCTToU
'운영체제보안' 카테고리의 다른 글
Dirty COW #1 Copy-on-Write (0) | 2024.12.06 |
---|---|
ToCTToU (Time of Check-to-Time of Use) Vulnerability (0) | 2024.12.06 |
Return-Oriented Programming (ROP) (0) | 2024.12.06 |
Chaining Function Calls (without arguments) (0) | 2024.12.05 |
Ret2Libc 정리 및 ROP 개념 (0) | 2024.12.05 |