이 정보는 Ubuntu 16.04 LTS 환경에서 실행 중인 바이너리의 보안 설정과 특성을 나타냅니다. 각 항목을 분석하여 해당 바이너리의 보안 강점을 설명하겠습니다.
분석
1. RELRO (Relocation Read-Only)
- 상태: Full RELRO
- 설명: Global Offset Table(GOT)의 엔트리들을 읽기 전용으로 설정합니다.
- 보안 이점:
- GOT overwrite 공격(동적 함수 호출 시 악의적인 주소로 리다이렉트)이 불가능합니다.
- 공격 가능성:
- Full RELRO에서는 GOT 공격을 수행할 수 없으므로, 이 부분은 안전합니다.
2. Stack Canary
- 상태: Canary found
- 설명: 함수 호출 시 반환 주소 바로 앞에 **스택 카나리(Stack Canary)**를 삽입하여, 스택 오버플로우로 인해 반환 주소가 덮어씌워지는 것을 방지합니다.
- 보안 이점:
- 스택 오버플로우를 악용해 함수 반환 주소를 덮어쓰는 공격을 방어할 수 있습니다.
- 카나리 값이 변조되면 프로그램이 강제 종료됩니다.
- 공격 가능성:
- Canary를 우회하려면 카나리 값을 유출하거나, Canary가 없는 영역을 활용한 공격이 필요합니다.
3. NX (No eXecute)
- 상태: NX enabled
- 설명: 데이터 영역(스택, 힙 등)에 저장된 코드의 실행을 금지합니다.
- 보안 이점:
- 쉘코드(Shellcode)를 스택이나 힙에 삽입하고 실행하는 전통적인 버퍼 오버플로우 공격을 방어합니다.
- 공격 가능성:
- NX가 활성화된 경우, **ROP(Return-Oriented Programming)**과 같은 기술을 사용하여 기존의 실행 가능한 코드 조각을 조합해 악의적인 동작을 수행할 수 있습니다.
4. PIE (Position Independent Executable)
- 상태: PIE enabled
- 설명: 프로그램의 실행 시점마다 코드와 데이터의 메모리 주소를 랜덤화하여 고정된 주소를 악용하는 공격을 방어합니다.
- 보안 이점:
- 실행 파일의 코드, 데이터 섹션이 항상 다른 주소에 매핑되므로 정적 주소 기반의 공격이 어려워집니다.
- 공격 가능성:
- PIE를 우회하려면 **정보 유출(Information Leakage)**을 통해 실제 메모리 주소를 알아내야 합니다.
- 주소를 유출하는 취약점(예: Format String, 메모리 덤프 등)을 찾는 것이 필요합니다.
종합 평가
이 바이너리는 여러 강력한 보안 메커니즘을 갖추고 있어, 익스플로잇을 시도하기 어려운 상태입니다.
보안 메커니즘 현재 상태 취약점/우회 가능성
RELRO | Full RELRO | GOT 공격 불가능 |
Stack Canary | Canary found | Canary 값을 유출하거나 우회해야 함 |
NX | NX enabled | 쉘코드 실행 불가능, ROP 필요 |
PIE | PIE enabled | 주소 랜덤화, 정보 유출 필요 |
공격 가능성 및 우회 방법
1. Canary 우회
- Canary 값을 메모리에서 유출하거나, Canary 보호를 우회해야 합니다.
- 가능성:
- Canary 유출은 Printf Format String 취약점 또는 메모리 누출을 통해 가능.
2. ROP 공격
- NX 보호로 인해 쉘코드 삽입 공격은 불가능하므로 ROP(Return-Oriented Programming) 기법을 활용해야 합니다.
- ROP를 위해 다음이 필요:
- 바이너리나 라이브러리 내에서 유효한 가젯(Gadget)을 찾기.
- 실행 흐름을 가젯으로 리다이렉트.
3. PIE 우회
- PIE 활성화로 정적 주소 기반 공격이 불가능하므로, 정보 누출 취약점이 필요합니다.
- 취약점 예:
- Printf Format String으로 메모리 주소를 유출.
- Stack/Heap Overflow로 메모리 덤프 유도.
공격 성공 시나리오
- Canary 유출:
- Printf Format String 취약점으로 Canary 값을 유출.
- Canary를 우회하여 스택 오버플로우 공격 성공.
- PIE 주소 유출:
- 메모리 누출 취약점으로 libc 또는 실행 파일의 실제 메모리 주소를 유출.
- ROP 기법으로 쉘 실행.
- ROP 체인 구성:
- NX 활성화를 우회하기 위해 가젯을 조합한 ROP 체인을 구성.
- libc 함수 호출(예: system("/bin/sh"))로 쉘 획득.
결론
이 바이너리는 강력한 보안 메커니즘으로 보호되고 있지만, 특정 취약점(정보 누출, Canary 유출 등)을 통해 우회 가능성이 있습니다. 공격 시:
- Canary 유출: Canary 값을 유출해야 스택 오버플로우를 실행할 수 있습니다.
- PIE 우회: PIE를 우회하려면 메모리 주소를 유출해야 합니다.
- ROP 활용: NX 보호로 인해 ROP 체인을 구성해야 합니다.
공격을 성공적으로 수행하려면 정보 유출 취약점을 우선적으로 찾아야 합니다. 😊
//g++ -o cpp_string cpp_string.cpp
#include <iostream>
#include <fstream>
#include <csignal>
#include <unistd.h>
#include <stdlib.h>
char readbuffer[64] = {0, };
char flag[64] = {0, };
std::string writebuffer;
void alarm_handler(int trash)
{
std::cout << "TIME OUT" << std::endl;
exit(-1);
}
void initialize()
{
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int read_file(){
std::ifstream is ("test", std::ifstream::binary);
if(is.is_open()){
is.read(readbuffer, sizeof(readbuffer));
is.close();
std::cout << "Read complete!" << std::endl;
return 0;
}
else{
std::cout << "No testfile...exiting.." << std::endl;
exit(0);
}
}
int write_file(){
std::ofstream of ("test", std::ifstream::binary);
if(of.is_open()){
std::cout << "Enter file contents : ";
std::cin >> writebuffer;
of.write(writebuffer.c_str(), sizeof(readbuffer));
of.close();
std::cout << "Write complete!" << std::endl;
return 0;
}
else{
std::cout << "Open error!" << std::endl;
exit(0);
}
}
int read_flag(){
std::ifstream is ("flag", std::ifstream::binary);
if(is.is_open()){
is.read(flag, sizeof(readbuffer));
is.close();
return 0;
}
else{
std::cout << "You must need flagfile.." << std::endl;
exit(0);
}
}
int show_contents(){
std::cout << "contents : ";
std::cout << readbuffer << std::endl;
return 0;
}
int main(void) {
initialize();
int selector = 0;
while(1){
std::cout << "Simple file system" << std::endl;
std::cout << "1. read file" << std::endl;
std::cout << "2. write file" << std::endl;
std::cout << "3. show contents" << std::endl;
std::cout << "4. quit" << std::endl;
std::cout << "[*] input : ";
std::cin >> selector;
switch(selector){
case 1:
read_flag();
read_file();
break;
case 2:
write_file();
break;
case 3:
show_contents();
break;
case 4:
std::cout << "BYEBYE" << std::endl;
exit(0);
}
}
}
소스코드다.
flag 파일 내용을 입력하여야 읽고 볼 수 있어야 flag를 획득할 수 있는 것으로 보인다
문제 제목이 cpp string인게 힌트인 것 같다
이 코드는 간단한 파일 시스템을 구현한 프로그램입니다. 사용자는 파일을 읽고 쓰며, 특정 파일(flag)의 내용을 프로그램에서 관리합니다. 다음은 코드의 주요 기능과 잠재적인 취약점을 분석한 결과입니다.
1. 주요 기능
1.1. 초기화 함수 (initialize)
- 설명:
- stdin과 stdout 버퍼를 비활성화하여 실시간 입출력을 보장.
- 30초의 타이머를 설정하고, 타이머가 만료되면 프로그램 종료.
1.2. 파일 읽기 (read_file)
- 설명:
- test 파일의 내용을 readbuffer에 읽어 들입니다.
- 파일이 존재하지 않으면 프로그램 종료.
- 버그/취약점:
- readbuffer의 크기(64바이트)만큼 파일 내용을 읽지만, 파일이 더 크면 초과된 데이터는 무시됩니다.
1.3. 파일 쓰기 (write_file)
- 설명:
- 사용자 입력을 받아 test 파일에 기록.
- 입력은 std::string(writebuffer)로 받아, C 스타일 문자열로 변환한 뒤 파일에 기록.
- 버그/취약점:
- 입력 데이터 크기 제한이 없음:
- 사용자 입력이 64바이트를 초과하면 프로그램이 의도한 데이터 크기를 초과하여 기록하려고 시도합니다.
- of.write(writebuffer.c_str(), sizeof(readbuffer));는 항상 64바이트를 쓰려고 시도하므로, 입력이 64바이트 미만인 경우 파일에 불필요한 데이터가 포함됩니다.
- 입력 데이터 크기 제한이 없음:
1.4. 플래그 파일 읽기 (read_flag)
- 설명:
- flag 파일 내용을 flag 버퍼에 읽음.
- 파일이 없으면 프로그램 종료.
- 버그/취약점:
- 읽은 데이터는 사용자에게 노출되지 않음(단순히 메모리에 저장).
1.5. 내용 표시 (show_contents)
- 설명:
- readbuffer 내용을 출력.
- 버그/취약점:
- readbuffer가 초기화되지 않거나 파일이 읽히지 않은 상태에서 호출될 경우, 이전 쓰레기 데이터를 출력.
1.6. 메인 함수
- 설명:
- 사용자 인터페이스를 통해 파일 읽기, 쓰기, 내용을 확인하거나 프로그램 종료.
- read_flag는 항상 read_file 전에 호출되며, 플래그 파일이 없는 경우 실행이 차단됨.
- 버그/취약점:
- 사용자 입력 selector의 값이 의도한 범위를 벗어날 경우 처리하지 않음.
- 예: 5 이상의 값이나 비정상적인 입력.
- 사용자 입력 selector의 값이 의도한 범위를 벗어날 경우 처리하지 않음.
2. 잠재적 취약점 및 공격 가능성
2.1. write_file 입력 크기 제한 없음
- 취약점:
- 사용자 입력에 크기 제한이 없으므로, 과도한 입력이 메모리 오염 및 이상 동작을 유발할 수 있습니다.
- 공격 가능성:
- 파일 오염: 입력 크기가 64바이트를 초과하면 test 파일에 의도하지 않은 데이터가 기록됩니다.
- DOS 공격: 매우 큰 입력으로 메모리를 고갈시킬 가능성.
2.2. readbuffer 초기화 문제
- 취약점:
- readbuffer는 read_file이 호출되기 전에는 초기화되지 않으므로, show_contents가 호출될 경우 쓰레기 데이터가 출력됩니다.
- 공격 가능성:
- 프로그램 메모리에 저장된 데이터를 유추할 수 있는 정보 누출(Information Leakage) 공격.
2.3. 플래그 보호 부족
- 취약점:
- read_flag는 플래그 파일 내용을 읽어 메모리에 저장하지만, 보호 장치가 부족합니다.
- 공격 가능성:
- 플래그 파일 내용은 메모리(flag 변수)에 저장되므로, 메모리 누출 취약점을 악용해 플래그를 유출할 가능성이 있습니다.
- 예: show_contents가 readbuffer를 출력하는데, 메모리 오염으로 인해 flag가 readbuffer에 복사되면 플래그 노출 가능.
3. 개선 방안
- 입력 크기 제한 추가 (write_file):
- 사용자 입력의 크기를 제한하여 메모리 오염 및 프로그램 충돌 방지.
std::cin >> std::setw(64) >> writebuffer;
- readbuffer 초기화:
- read_file 호출 전 readbuffer를 명시적으로 초기화.
memset(readbuffer, 0, sizeof(readbuffer));
- 불필요한 데이터 쓰기 방지:
- write_file에서 실제 사용자 입력 크기만큼만 파일에 기록.
of.write(writebuffer.c_str(), writebuffer.size());
- 사용자 입력 검증:
- selector 값이 허용된 범위 내에 있는지 확인.
if (selector < 1 || selector > 4) { std::cout << "Invalid input!" << std::endl; continue; }
- 플래그 보호 강화:
- flag 파일을 메모리에 로드하지 않고, 직접 접근을 제한하거나 암호화.
4. 공격 시나리오
- 입력 크기 초과로 메모리 오염:
- write_file에서 초과 입력으로 메모리를 덮어쓰거나 프로그램 이상 동작 유발.
- 메모리 누출로 플래그 유출:
- readbuffer와 flag가 동일한 메모리 공간을 공유하도록 조작하여 show_contents로 플래그 출력.
결론
이 프로그램은 간단한 파일 시스템을 구현했지만, 여러 가지 취약점이 존재합니다. 특히, 입력 검증 부족과 메모리 초기화 문제로 인해 정보 누출 및 프로그램 충돌 가능성이 있습니다. 위 개선 방안을 적용하여 보안을 강화할 수 있습니다. 😊
**cpp_string**은 주어진 C++ 코드에서 실행 파일 이름으로 지정된 프로그램 이름입니다. 이 프로그램은 간단한 파일 시스템처럼 작동하며, 파일 읽기, 쓰기, 내용을 표시할 수 있는 기능을 제공합니다. 문제를 해결하려면 이 프로그램의 동작을 분석하고, 약점을 찾아 이를 활용하여 플래그를 추출하거나 특정 목표를 달성하는 것이 목표입니다.
주어진 프로그램의 동작
1. 주요 기능
이 프로그램은 다음과 같은 메뉴를 제공합니다:
- Read File:
- test 파일의 내용을 읽어서 readbuffer에 저장.
- 플래그 파일(flag)도 읽어서 메모리에 로드.
- Write File:
- 사용자 입력을 받아 test 파일에 작성.
- Show Contents:
- readbuffer의 내용을 화면에 출력.
- Quit:
- 프로그램 종료.
문제 풀이 목표
문제 풀이의 목표는 보통 다음과 같은 작업 중 하나입니다:
- 플래그 추출:
- flag 파일의 내용을 프로그램의 동작을 통해 읽고 표시.
- 취약점 이용:
- 프로그램의 입력 검증 부족이나 메모리 관리 취약점을 악용하여 제한된 데이터를 조작하거나 노출.
- 특정 작업 수행:
- 예: 파일 내용을 덮어쓰기, 예상치 못한 데이터를 읽기 등.
문제 풀이 접근 방법
1. 코드 분석
- read_flag 함수:
- 플래그 파일(flag)의 내용을 읽고 flag 변수에 저장.
- 이 내용은 메모리에만 저장되고 직접 출력되지 않습니다.
- show_contents 함수:
- readbuffer 내용을 출력.
- read_file로 파일(test)의 내용을 읽어야 정상적으로 데이터를 확인 가능.
- write_file 함수:
- 사용자 입력을 받아 test 파일에 작성.
- 입력 크기 제한이 없어 메모리 오염 가능.
2. 취약점 탐지 및 활용
취약점 1: 입력 크기 제한 부족 (Write File)
- 사용자 입력에 크기 제한이 없어 초과 입력으로 메모리 오염 가능.
- writebuffer에 데이터를 초과 입력하여 readbuffer나 flag와 같은 메모리 공간을 덮어쓸 가능성.
취약점 2: 정보 노출 가능성 (Show Contents)
- readbuffer를 출력하지만, 제대로 초기화되지 않은 경우 쓰레기 데이터나 메모리에 저장된 다른 데이터(flag 등)를 출력할 가능성.
취약점 3: 플래그 보호 부족
- 플래그 데이터는 메모리에 저장되며, 직접 접근하지 않아도 메모리 누출 취약점을 통해 읽어낼 수 있음.
공격 시나리오
목표: 플래그 파일의 내용(flag)을 추출.
- 초기화:
- 프로그램을 실행하고 read_file을 호출하여 flag 내용을 메모리에 로드.
- 메모리 덮어쓰기:
- write_file을 이용하여 입력 크기 초과로 메모리 덮어쓰기 시도.
- readbuffer가 flag 내용을 가리키도록 조작.
- 내용 표시:
- show_contents를 호출하여 flag 내용을 출력.
즉 wirte_file이 입력 크기 제한이 없어서, 사용자 입력 받아-> test파일에 작성
이test파일을 read_file로 읽어와서, show_contents 함수가 작동 ,readbuffer 내용을 출력,
문제는 그게 읽기 크기 제한을 초과해서, read_flag 함수가 호출되어 flag 변수 튀어나와, flag 파일이 보이는거임
학원가야함;;갔다와서 풉니다
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[109] IT 비전공자 [dreamhack]mmapped문제 풀기 (1) | 2024.12.28 |
---|---|
[108] IT 비전공자 [dreamhack]darimchal_001문제 풀기 (0) | 2024.12.27 |
[107] IT 비전공자 [dreamhack][CodeEngn] Malware L07문제 풀기 (2) | 2024.12.25 |
[106] IT 비전공자 [dreamhack]__environ문제 풀기 (0) | 2024.12.24 |
[105] IT 비전공자 [dreamhack]Robot Only문제 풀기 (1) | 2024.12.23 |