DDSS: 단계별 설명
Source: Dev.to
중요 안전 주의 – 이 가이드는 오직 로컬 머신에서 학습용입니다.
취약한 코드를 인터넷에 노출하지 마세요.
1️⃣ 사전 요구 사항
| 필요한 것 | 필요한 이유 |
|---|---|
| Docker가 설치된 컴퓨터 | Docker는 앱과 데이터베이스를 격리된 컨테이너에서 실행합니다. |
| Python 3.x (Python 패키지를 로컬에 설치하려는 경우) | Flask 코드와 pip 명령어에 필요합니다. |
| 터미널 / 명령 프롬프트 | 가이드에 표시된 명령을 실행하기 위해. |
Docker가 아직 설치되지 않았다면, docker.com 에서 다운로드하고 운영 체제에 맞는 설치 안내를 따르세요.
설치를 테스트해 보세요:
docker --version
다음과 같은 형태로 Docker 버전이 표시됩니다 Docker version 24.0.5, build abcdefg.
2️⃣ 프로젝트 파일 받기
- Download (다운로드) 하라는 ZIP 아카이브를 받습니다 (
ddss-2025-assignment2-rc-main-2.zip파일). - Unzip (압축 해제) 합니다:
| OS | How to unzip |
|---|---|
| Windows | ZIP 파일을 오른쪽 클릭 → Extract All… |
| macOS | ZIP 파일을 더블 클릭 (자동으로 압축이 해제됩니다). |
| Linux | 터미널을 열고 unzip ddss-2025-assignment2-rc-main-2.zip 명령을 실행합니다. |
압축을 풀면 (예: ddss-2025-assignment2-rc-main-2) 다음과 같은 폴더가 생성됩니다:
- Python 소스 파일 (
app.py등) - Docker 관련 파일 (
Dockerfile,docker-compose.yml,docker-compose-python-psql.sh) - 기타 자산 (템플릿, 정적 파일, README 등)
3️⃣ Docker 시작
- Docker Desktop을 엽니다 (또는 Docker 데몬을 실행합니다).
- 실행 중인지 확인합니다 – 작업 표시줄 / 메뉴 막대에 Docker 고래 아이콘이 표시되어야 합니다.
4️⃣ 터미널 / 명령 프롬프트 열기
| 플랫폼 | 열기 방법 |
|---|---|
| Windows | Command Prompt(또는 PowerShell)를 검색합니다. |
| macOS | Terminal을 엽니다 (⌘ Space → “Terminal”). |
| Linux | 선호하는 터미널 에뮬레이터를 엽니다. |
5️⃣ 프로젝트 폴더로 이동
cd ~/Downloads # 또는 ZIP 파일을 저장한 위치
cd ddss-2025-assignment2-rc-main-2
“No such file or directory”(해당 파일이나 디렉터리가 없습니다) 오류가 발생하면, 내용물을 확인하세요(macOS/Linux에서는 ls, Windows에서는 dir` 사용) 그리고 폴더 이름을 알맞게 수정하십시오.
6️⃣ 필요한 Python 패키지 설치
pip install flask psycopg2-binary werkzeug bandit
| 패키지 | 기능 설명 |
|---|---|
| flask | Python용 최소 웹 프레임워크. |
| psycopg2‑binary | Python용 PostgreSQL 드라이버. |
| werkzeug | Flask에서 사용하는 유틸리티 라이브러리. |
| bandit | 정적 보안 분석기 (선택 사항이지만 유용함). |
격리된 환경을 선호한다면, 먼저 virtualenv를 생성하세요 (python -m venv venv && source venv/bin/activate).
7️⃣ Docker 컨테이너 빌드 및 시작
프로젝트에는 Docker Compose를 실행하는 도우미 스크립트가 포함되어 있습니다.
# 스크립트를 실행 가능하게 만들기 (첫 번째 실행 시에만 필요)
chmod +x docker-compose-python-psql.sh
# 실행
./docker-compose-python-psql.sh
무슨 일이 일어나나요
- Docker Compose가 두 개의 컨테이너를 빌드합니다:
- Python/Flask 애플리케이션 (
web). - PostgreSQL 데이터베이스 (
db).
- Python/Flask 애플리케이션 (
- 이미지가 Docker Hub에서 풀됩니다 (몇 분 정도 걸릴 수 있습니다).
- 스크립트가 완료되면 “finished building”와 같은 메시지가 표시됩니다.
8️⃣ (Optional) DB 컨테이너 안에서 psql 셸 열기
두 번째 터미널 탭/창을 열고 다음을 실행합니다:
docker exec -it db psql -U ddss-database-assignment-2 -d ddss-database-assignment-2
PostgreSQL 프롬프트에 들어갑니다:
ddss-database-assignment-2=#
\q 로 종료합니다.
테이블을 확인하거나 디버깅할 때 유용합니다.
9️⃣ 웹 애플리케이션에 접근하기
| Action | URL |
|---|---|
| 홈 페이지 열기 | http://localhost:8080 |
| 새 사용자 등록 | http://localhost:8080/register |
모던 브라우저(Chrome, Firefox, Edge, Safari)를 사용하세요.
- 등록 일반 계정을 만듭니다(원하는 사용자명/비밀번호 선택).
- 이제 로그인하여 과제의 다양한 부분을 탐색할 수 있습니다.
🔟 취약점 시연
10.1 SQL Injection (취약 버전)
- 로그인 페이지로 이동합니다(보통
/login또는/part1). - 다음 값을 입력합니다:
| 필드 | 페이로드 |
|---|---|
| 사용자 이름 | ' OR '1'='1' -- |
| 비밀번호 | 아무 것이나(예: blah) |
- Login 버튼을 클릭합니다.
결과: “VULNERABLE LOGIN SUCCESS” 와 같은 메시지가 표시됩니다.
동작 원리
앱은 다음과 유사한 쿼리를 생성합니다:
SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = 'blah';
OR '1'='1'은 항상 참입니다.--은 나머지 라인을 주석 처리하여 비밀번호 검사를 제거합니다.- 쿼리가 행을 반환하므로 유효한 자격 증명 없이 로그인에 성공합니다.
10.2 SQL Injection (보안 버전)
- 동일한 페이로드를 보안 로그인 폼에 사용합니다(보통
/secure-login또는 다른 경로). - 이제 앱은 파라미터화된 쿼리(prepared statements)를 사용하므로 입력값이 코드가 아니라 데이터로 처리됩니다.
결과: **“Invalid credentials”(또는 유사한) 메시지가 표시됩니다 – 인젝션이 실패합니다.
📚 배운 내용
| 개념 | 가이드에서 나타난 방식 |
|---|---|
| Docker containers | Flask 앱과 PostgreSQL 데이터베이스를 격리합니다. |
| Flask | 취약한 앱에 사용된 최소한의 Python 웹 프레임워크입니다. |
| SQL injection | 로그인 폼에 ' OR '1'='1' -- 를 삽입하여 시연했습니다. |
| Parameterised queries | 삽입을 차단하는 해결책입니다. |
| XSS (cross‑site scripting) | (발췌본에는 포함되지 않았지만 과제의 일부입니다.) |
| Bandit | Python 코드의 보안 문제를 스캔하는 도구입니다. |
✅ 다음 단계
-
Run Bandit on the source code to see what it flags:
bandit -r . -
Fix the XSS vulnerability (look for places where user input is rendered without escaping).
-
Write a short report describing each vulnerability, how you exploited it, and how you mitigated it.
Good luck, and remember: always test security flaws offline and never expose vulnerable code to the public internet!
로그인 실패 설명
Message: LOGIN FAILED.
Why?
보안 버전은 prepared statements를 사용하여 SQL 인젝션을 방지합니다. 입력값은 실행 가능한 코드가 아니라 데이터로 처리됩니다.
Source: …
Step 11 – Test Part 2: Session Authorization & More
1. Not Logged In
- /part2.html 및 /part3.html에 접근해 보세요.
- 기대 동작: /part1.html(로그인 필요)으로 리디렉션되어야 합니다.
2. Logged In (Secure Way)
- secure 로그인 폼을 통해 정상적으로 로그인합니다.
- 그 후 /part2.html 및 /part3.html에 접근하면 정상적으로 로드됩니다.
Why?
취약한 로그인으로 들어가더라도, 애플리케이션은 세션(예: 쿠키)을 사용해 인증 상태를 추적합니다. 유효한 세션 없이는 보호된 페이지에 접근할 수 없습니다.
XSS (Cross‑Site Scripting) 시연
취약한 폼
-
메시지 폼(아마 /part2 경로)에서 다음 페이로드를 제출합니다:
alert('XSS') -
페이지를 새로 고칩니다.
결과: 알림 팝업이 표시됩니다.
이유:
앱이 원시 스크립트를 데이터베이스에 그대로 저장하고, 이스케이프 없이 렌더링하기 때문에 브라우저가 JavaScript로 실행합니다.
보안된 폼
- 동일한 페이로드(
alert('XSS'))를 제출합니다. - 페이지를 새로 고칩니다.
결과: 팝업이 나타나지 않으며, 스크립트가 일반 텍스트로 표시됩니다.
이유:
보안 버전은 출력 시 이스케이프를 수행합니다(예: Flask의 Jinja 자동 이스케이프 사용). <를 <와 같이 변환해 스크립트를 무해하게 만듭니다.
메시지 목록
가이드에는 예시 메시지가 표시됩니다. 귀하의 메시지는 다를 수 있지만, 동작(실행 vs. 이스케이프)은 동일해야 합니다.
보고서 요약 표
다음 마크다운 표를 과제 보고서에 복사하십시오:
| 버전 | 취약점 | 결과 |
|---|---|---|
| 취약 | 저장된 XSS | JS 실행 |
| 안전 | 이스케이프된 출력 | 안전한 표시 |
이제 SQL injection(로그인 및 데이터 접근을 위한)과 XSS를 시연했으며, 그에 대한 완화 방안도 포함되었습니다.
SQL Injection Demonstration (Books Query)
Vulnerable Query
-
In the insecure form (look for “price more than”), enter:
0 OR 1=1 -- -
Submit the form.
Result: All books are listed.
Why?
The injection tricks the SQL engine into ignoring the price condition, returning every row (similar to a login bypass).
Secure Query
- Use the same input (
0 OR 1=1 --). - Expected behavior: no books are returned or the query fails safely.
Why?
Parameterized (prepared) statements prevent the injection from altering the query logic.
최종 팁
- 문제 해결: 무언가 실패하면 터미널에서 오류를 확인하세요.
docker-compose down으로 Docker를 재시작한 뒤 설정 스크립트를 다시 실행합니다. - 학습 포인트: 이 연습은 웹 애플리케이션에서 입력 검증, 준비된 문장, 출력 이스케이프가 왜 중요한지를 보여줍니다.
- 보고서 안내: 성공 및 실패 시도의 스크린샷을 캡처하고, 위와 같이 각 단계를 설명하며 요약 표를 포함합니다.
- 정리: 작업이 끝나면 프로젝트 폴더에서
docker-compose down명령으로 Docker 컨테이너를 중지합니다.
단계가 명확하지 않다면 해당 부분에 대해 자유롭게 질문하세요. 할 수 있어요—컴퓨터 과학은 실험하는 것이 전부입니다! 🚀