No description
  • PHP 63.5%
  • JavaScript 27.3%
  • CSS 9.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
hardline7 66c9909218 SSRF 실습용 mhg.txt를 저장소에 포함 + 실패 사유 화면 표시
- mhg.txt: 참가자 명단(가짜) — clone하면 /var/www/html/mhg.txt로 딸려옴.
  SSRF 취약검사에 file:///var/www/html/mhg.txt 넣으면 이 명단이 나옴.
- app.js: SSRF에서 허용됐는데 body가 비면 실패 사유(note)를 회색으로 표시.
2026-09-02 14:49:11 +09:00
api 참가자별 가짜 급여명세 시드 추가 — 각자 자기 것을 털어보는 실습용 2026-09-02 12:41:52 +09:00
assets SSRF 실습용 mhg.txt를 저장소에 포함 + 실패 사유 화면 표시 2026-09-02 14:49:11 +09:00
seed_files 참가자별 가짜 급여명세 시드 추가 — 각자 자기 것을 털어보는 실습용 2026-09-02 12:41:52 +09:00
uploads 해킹 타임 실습용 t-box 취약 샘플 앱 추가 (순수 PHP + PostgreSQL) 2026-09-01 00:20:51 +09:00
.gitignore 해킹 타임 실습용 t-box 취약 샘플 앱 추가 (순수 PHP + PostgreSQL) 2026-09-01 00:20:51 +09:00
db.php 해킹 타임 실습용 t-box 취약 샘플 앱 추가 (순수 PHP + PostgreSQL) 2026-09-01 00:20:51 +09:00
index.php SQL 인젝션 실습 추가 — 취약한 파일 검색 + users 테이블 비번 유출 2026-09-02 12:08:06 +09:00
INSTALL.md AI 에이전트용 설치 지시서 INSTALL.md 추가 2026-09-01 02:20:45 +09:00
mhg.txt SSRF 실습용 mhg.txt를 저장소에 포함 + 실패 사유 화면 표시 2026-09-02 14:49:11 +09:00
README.md 해킹 타임 실습용 t-box 취약 샘플 앱 추가 (순수 PHP + PostgreSQL) 2026-09-01 00:20:51 +09:00
schema.sql 참가자별 가짜 급여명세 시드 추가 — 각자 자기 것을 털어보는 실습용 2026-09-02 12:41:52 +09:00
switch_role.php 해킹 타임 실습용 t-box 취약 샘플 앱 추가 (순수 PHP + PostgreSQL) 2026-09-01 00:20:51 +09:00

t-box 교육용 샘플 (의도적으로 취약한 버전)

바이브 코딩 워크숍의 해킹 타임 실습용 샘플 앱입니다. 순수 PHP + PostgreSQL로 만들었고, 실습 시나리오가 반드시 재현되도록 취약점을 일부러 남겨두었습니다.

⚠️ 이 코드는 교육용입니다. 실제 서비스에 절대 사용하지 마세요. 반드시 참가자 개인 VM(폐쇄 환경)에서만 실행합니다.

왜 이 저장소가 필요한가

참가자가 AI에게 "취약하게 만들어줘"라고 요청해도, 요즘 AI는 보안을 챙겨서 권한 검사를 넣어버리는 경우가 많습니다. 그러면 해킹 타임 실습이 성립하지 않습니다. 이 저장소는 강사용 안전망입니다. 참가자의 앱에서 취약점이 재현되지 않을 때 이걸 내려받아 실습을 진행하세요.

설치

1. 필요한 것

sudo apt update
sudo apt install -y nginx php-fpm php-pgsql postgresql

2. DB 만들기

sudo -u postgres psql -c "CREATE USER tbox WITH PASSWORD 'tbox';"
sudo -u postgres psql -c "CREATE DATABASE tbox OWNER tbox;"
psql "postgresql://tbox:tbox@127.0.0.1/tbox" -f schema.sql

schema.sql은 테이블과 함께 예시 파일 5개(public 2 · internal 2 · admin-only 1)를 넣어줍니다. 해킹 타임을 바로 시작할 수 있습니다.

3. 코드 배치

sudo mkdir -p /var/www/html
sudo chown -R $USER /var/www/html
cp -r . /var/www/html/
chmod 777 /var/www/html/uploads

4. nginx 설정

/etc/nginx/sites-available/tbox 에 아래를 넣고 활성화합니다. (php8.2-fpm.sock 부분은 설치된 PHP 버전에 맞게 바꾸세요 — ls /run/php/로 확인)

server {
    listen 80;
    server_name _;
    root /var/www/html;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}
sudo ln -sf /etc/nginx/sites-available/tbox /etc/nginx/sites-enabled/tbox
sudo nginx -t && sudo systemctl reload nginx

브라우저에서 내 도메인으로 접속하면 목록이 보입니다.

파일 구조

파일 역할
index.php 화면 (목록 · 업로드 · URL 가져오기)
db.php DB 연결, 현재 사용자, JSON 응답 도우미
switch_role.php 역할 전환 (교육용 — 진짜 로그인 대신)
api/files.php 목록 조회 / 삭제 — 취약점 A·B
api/upload.php 업로드 — 취약점 C 준비 (검증 없음)
api/download.php 다운로드 — 권한 검사 없음
api/fetch_url.php URL 검사 — SSRF 실습 (취약/방어 비교)
assets/app.js 화면 동작 — 취약점 A·B·C
schema.sql 테이블 + 예시 데이터 5개

심어둔 취약점 (강사용 정답지)

A. 프론트엔드 권한 우회 → 삭제

  • 어디에: assets/app.js (버튼을 display:none으로 숨김) + api/files.php (DELETE에 권한 검사 없음)
  • 재현: Employee로 전환 → 삭제 버튼 안 보임 → F12 Elements에서 style="display:none" 제거 → 버튼 클릭 → 삭제됨
  • 콘솔로도 가능: fetch('api/files.php?id=1', {method:'DELETE'}).then(r=>r.json()).then(console.log)
  • 고치는 법: api/files.php의 DELETE 분기에서 current_user()['role']을 확인하고 권한 없으면 403 + 감사 로그

B. 숨긴 데이터가 API 응답에 노출

  • 어디에: api/files.php GET (전체 조회) + assets/app.js의 VISIBLE_BY_ROLE (화면에서만 필터)
  • 재현: Employee로 전환 → 화면엔 admin-only 파일 안 보임 → F12 Network 탭 → api/files.php 응답 확인 → 급여명세_2026.txt가 그대로 보임
  • 고치는 법: SQL의 WHERE access_level IN (...)으로 서버에서 걸러서 내려주기

C. XSS (파일명·설명)

  • 어디에: api/upload.php (검증 없이 저장) + assets/app.js의 tr.innerHTML (이스케이프 없이 출력)
  • 재현: 파일 설명에 <img src=x onerror="alert('xss')"> 입력 후 업로드 → 목록 화면에서 알림창이 뜸
  • 고치는 법: 출력 시 이스케이프(textContent 사용 또는 서버에서 htmlspecialchars)

D. SSRF

  • 어디에: api/fetch_url.php
  • 재현: URL 칸에 http://127.0.0.1:3000 또는 http://169.254.169.254/latest/meta-data 입력 → 취약한 검사는 통과시킴
  • 비교: 같은 URL로 방어된 검사를 고르면 차단 사유가 나옴
  • 고치는 법: check_safe()가 목표 모습 — http/https만 허용, DNS 해석 후 사설·루프백·링크로컬 IP 차단

E. 그 밖에 (실습 후반부용)

  • 파일 크기·확장자 제한 없음 (api/upload.php)
  • 감사 로그 테이블(audit_logs)은 있지만 아무도 기록하지 않음
  • 목록에 페이지네이션·검색 없음

실습 후 되돌리기

git checkout .        # 수정한 내용 되돌리기
psql "postgresql://tbox:tbox@127.0.0.1/tbox" -f schema.sql   # 데이터 초기화