Taeyoung Kim

Cloud & Platform

웹 보안 및 Docker 활용 실습

웹 보안 및 Docker 활용 실습 학습 내용을 정리한 백필 노트입니다.

이 글은 2025년 학습 기록을 블로그 형식으로 정리한 백필 노트입니다.

1. Docker를 활용한 실습 환경 구축

1-1. Azure 가상머신 생성 및 Docker 설치

취약점 분석 및 실습을 위한 가상 환경을 Azure에 구성하고 Docker를 설치합니다.

  • 가상머신(VM) 생성:
    • 리소스 그룹: docker (신규)
    • 가상 머신 이름: docker
    • 지역: Canada Central
    • 이미지: Ubuntu Server 24.04 LTS
    • 크기: Standard_D2s_v3 (2 vCPU, 8 GiB 메모리)
    • 인바운드 포트 규칙: HTTP (80), HTTPS (443), SSH (22) 허용
  • Docker 설치:
    1. 관리자 권한으로 전환합니다.Bash

      sudo su
      
    2. 패키지 목록을 업데이트하고 Docker를 설치합니다.Bash

      sudo apt update && sudo apt install docker.io -y
      
    3. 설치된 Docker 정보를 확인하여 정상 설치 여부를 검증합니다.Bash

      docker info
      

1-2. Flask 애플리케이션 컨테이너화

샘플 Flask 애플리케이션을 Git에서 복제하여 Docker 이미지로 빌드하고 Docker Hub에 배포합니다.

  • 소스 코드 복제:Bash

    git clone https://github.com/joozero/amazon-eks-flask.git
    cd amazon-eks-flask
    
  • Dockerfile 분석:Dockerfile

    FROM python:3.9-alpine            # 베이스 이미지 지정
    LABEL Author="joozero@amazon.com" # 작성자 정보WORKDIR /app                      # 작업 디렉토리 설정COPY requirements.txt requirements.txt # 의존성 파일 복사RUN pip3 install -r requirements.txt   # 의존성 설치COPY . .                               # 프로젝트 전체 복사CMD ["python3", "app.py"]              # 컨테이너 시작 명령어
    
  • 이미지 빌드 및 테스트:

    1. docker build 명령어로 이미지를 생성합니다.Bash

      docker build -t my-flask-app:latest . -f Dockerfile
      
    2. 생성된 이미지를 확인합니다 (docker images).

    3. 이미지 생성 히스토리를 확인합니다 (docker history my-flask-app).

    4. 컨테이너를 실행하여 애플리케이션을 테스트합니다.Bash

      docker stop $(docker ps -a -q) # 기존 컨테이너 중지
      docker run -d -p 80:8080 --name my-app my-flask-app:latest # 컨테이너 실행
      
  • Docker Hub에 릴리즈 (Release):

    1. Docker Hub에 로그인합니다. (사전에 Access Token 발급 필요)Bash

      docker login docker.io -u [사용자명]
      
    2. Docker Hub 사용자명에 맞게 이미지에 태그를 지정합니다.Bash

      docker tag my-flask-app:latest docker.io/[사용자명]/my-flask-app:latest
      
    3. 이미지를 Docker Hub로 푸시(업로드)합니다.Bash

      docker push docker.io/[사용자명]/my-flask-app:latest
      

    팁: 업로드 후 이미지가 바로 보이지 않을 경우, docker search <이미지> 명령어로 레지스트리 등록 여부를 확인할 수 있습니다.

1-3. Docker 이미지 보안 모범 사례

안전한 Docker 이미지를 구성하기 위한 주요 보안 검사 항목입니다.

  • 공식 이미지 사용: 신뢰할 수 있는 공식 이미지를 기반으로 사용합니다.
  • 레이어 최소화: 다단계 빌드를 활용하여 이미지 레이어 수를 줄입니다.
  • 특정 버전 명시: latest 태그 대신 명확한 버전을 지정하여 잠재적 문제를 방지합니다.
  • Docker 데몬 보안: TLS 암호화를 사용하여 데몬(2375 포트)을 보호합니다.
  • 권한 제한: USER 지시어를 사용해 non-root 사용자로 컨테이너를 실행합니다.
  • 불필요한 소프트웨어 제거: 공격 표면을 줄이기 위해 불필요한 패키지를 제거합니다.
  • 취약점 스캔: Trivy, Clair와 같은 도구로 이미지를 스캔합니다.
  • ADD 대신 COPY 사용: ADD는 URL 및 압축 해제 기능으로 인한 보안 위협이 있으므로 COPY 사용을 권장합니다.

1-4. 취약한 웹 애플리케이션 설치

  • bWAPP 설치:Bash

    docker run -d --name bwapp -p 8080:80 mupersei/bwapp
    

    이후 localhost:8080/install.php에 접속하여 초기 설정을 완료합니다.

  • DVWA 설치 및 설정:

    1. DVWA 컨테이너를 실행합니다.Bash

      docker run -d -p 8888:80 --name dvwa vulnerables/web-dvwa
      
    2. 컨테이너 내부 셸에 접근합니다.Bash

      docker exec -it dvwa /bin/bash
      
    3. PHP 설정을 변경하여 원격 파일 포함(RFI)을 허용합니다.Bash

      # /etc/php/7.0/apache2/php.ini 파일 수정
      # allow_url_include = Off -> On 으로 변경
      vim /etc/php/7.0/apache2/php.ini
      
    4. 컨테이너를 재시작하고 localhost:8888로 접속합니다. (ID: admin / PW: password)Bash

      exit
      docker restart dvwa
      
    5. 로그인 후 Create / Reset Database 버튼을 클릭하여 데이터베이스를 초기화합니다.


2. 웹 해킹 실습을 위한 기초

2-1. 주요 도구 및 학습 플랫폼

  • Burp Suite: 웹 프록시 도구로, HTTP/HTTPS 트래픽을 가로채고 분석/변조하는 데 사용됩니다. (Target, Proxy, Intruder, Repeater 등 주요 기능)
  • Load of SQL Injection (LOS): SQL Injection 공격 실습을 위한 무료 CTF 플랫폼.
  • PortSwigger Web Security Academy: 웹 보안 기술 교육을 위한 무료 온라인 학습 플랫폼으로, 다양한 실습 랩을 제공합니다.

2-2. 웹 기초 (HTML, CSS, JavaScript)

  • HTML: 웹 페이지의 구조와 내용을 정의하는 마크업 언어. (&lt;h1>, &lt;p>, &lt;a>, &lt;img> 등 주요 태그)
  • CSS: HTML 요소의 디자인과 스타일을 지정하는 언어. (선택자, color, font-size, margin 등 주요 속성)
  • JavaScript: 웹 페이지에 동적인 기능을 부여하는 프로그래밍 언어. (변수 선언 var, let, const의 차이점, 함수, 이벤트 처리 등)

2-3. 브라우저 개발자 도구

모든 최신 브라우저에 내장된 웹 분석 및 디버깅 도구입니다.

  • Elements: HTML(DOM) 및 CSS 실시간 확인 및 수정.
  • Console: JavaScript 코드 실행, 에러 로그 확인.
  • Network: 모든 네트워크 요청 모니터링, API 호출 분석.
  • Application: 로컬/세션 스토리지, 쿠키 등 브라우저 저장 데이터 확인.

3. 클라이언트 사이드 공격 실습: JavaScript 취약점 (DVWA)

3-1. DVWA - JavaScript Attacks (Low Level)

  • 취약점: 서버 측 검증 없이 클라이언트 측 JavaScript 코드만으로 입력값을 검증합니다.

  • 코드 분석: 사용자가 "success"를 입력하면 rot13 암호화 후 md5 해시를 적용하여 토큰을 생성하는 generate_token() 함수가 존재합니다.JavaScript

    function generate_token() {
        var phrase = document.getElementById("phrase").value;
        document.getElementById("token").value = md5(rot13(phrase));
    }
    
  • 공격 방법:

    1. 문제에서 요구하는 문자열 'success'를 동일한 로직으로 변환합니다.
    2. md5(rot13("success"))'38581812b435834ebf84ebcc2c6424d6'
    3. 변환된 값을 Phrase와 Token 입력란에 각각 넣고 제출하여 검증을 우회합니다.

3-2. DVWA - JavaScript Attacks (Medium Level)

  • 취약점: 입력값을 단순히 뒤집는(reverse) 로직을 사용하며, 약간의 난독화가 적용되어 있습니다.

  • 코드 분석: Javascript beautifier와 같은 도구로 난독화된 코드를 분석합니다.JavaScript

    // 문자열을 뒤집는 함수
    function do_something(e) {
        for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
        return t
    }
    // "XX" + phrase 값 + "XX" 를 합친 후 뒤집어서 토큰 생성
    function do_elsesomething(e) {
        document.getElementById("token").value = do_something(e + document.getElementById("phrase").value + "XX")
    }
    
  • 공격 방법: 분석된 로직에 따라 "success" 문자열을 처리하여 올바른 토큰 값을 생성 후 제출합니다.

3-3. DVWA - JavaScript Attacks (High Level)

  • 취약점: 다단계 함수 호출과 SHA256 해시를 사용하며, 코드가 고도로 난독화되어 있습니다.

  • 코드 분석:

    1. de4js와 같은 전문 디-난독화 도구를 사용하여 코드를 복원합니다.
    2. 복원된 코드는 SHA256 라이브러리와 토큰 생성 로직으로 구성됩니다.
    • token_part_1: 입력된 phrase 값을 뒤집어 토큰의 초기값으로 설정.
    • token_part_2: 페이지 로드 300ms 후, sha256("XX" + 현재_토큰값)을 계산하여 갱신.
    • token_part_3: 제출 버튼 클릭 시, sha256(현재_토큰값 + "ZZ")를 계산하여 최종 토큰 생성.
  • 공격 방법:JavaScript

    1. 브라우저 개발자 도구의 콘솔을 엽니다.
    2. 난독화 해제된 전체 JS 코드를 붙여넣어 함수(sha256, do_something 등)를 재정의합니다.
    3. 분석된 토큰 생성 순서에 따라 명령어를 순차적으로 실행하여 최종 토큰 값을 계산합니다.
    document.getElementById("phrase").value = "success";
    document.getElementById("token").value = do_something("success");
    document.getElementById("token").value = sha256("XX" + document.getElementById("token").value);
    document.getElementById("token").value = sha256(document.getElementById("token").value + "ZZ");
    document.forms[0].submit(); // 폼 자동 제출
    

4. 서버 사이드 공격 실습: PHP 및 명령어 주입

4-1. PHP 기초 및 취약점 이해

  • PHP: 서버 사이드에서 동적 웹 페이지를 생성하는 스크립트 언어. HTML과 결합이 용이하고 다양한 데이터베이스와 연동됩니다.
  • 취약점 학습 이유: 오래된 역사와 느슨한 문법 특성으로 인해 다양한 종류의 취약점이 발견되어, 보안 원리 학습에 최적화된 환경을 제공합니다. (예: include($_GET['page']);와 같은 원격 파일 포함(RFI) 취약점 코드)

4-2. DVWA - Command Injection (Low, Medium, High Level)

  • 취약점 원리: shell_exec()와 같은 함수 사용 시 사용자 입력값을 검증 없이 명령어에 그대로拼接하여 발생하는 취약점. 명령어 구분자(;, &, | 등)를 이용해 악의적인 명령을 추가 실행할 수 있습니다.
  • Low Level: 필터링이 전혀 없어 ;를 사용하여 ping -c 4 ; pwd와 같이 간단히 공격 가능합니다.
  • Medium Level: &&;를 필터링하지만, | 또는 &와 같은 다른 구분자로 우회 가능합니다.
  • High Level: 다양한 특수문자를 필터링하지만, '| '(파이프 뒤에 공백)와 같이 특정 패턴만 필터링하는 허점을 이용해 |pwd와 같이 공백 없이 붙여서 공격하여 우회할 수 있습니다.

4-3. PortSwigger - OS Command Injection (Simple & Blind)

  • Simple Case: 제품 재고 확인 기능에서 productId 값에 명령어 주입이 가능. & whoami와 같은 페이로드를 전달하여 whoami 명령어의 실행 결과를 응답으로 확인합니다.
  • Blind Case: 피드백 제출 기능에서 명령어 주입은 가능하나 실행 결과가 반환되지 않음. email=x@x.com; sleep 10 #와 같이 sleep 명령어를 주입하여 서버 응답이 10초 지연되는 것을 확인함으로써 취약점 존재를 증명합니다.