Hack&Dev/Web

Flask 디버그 모드에서의 LFI(Local File Inclusion) 및 PIN 탈취 취약점

스우스우03 2025. 2. 22. 20:21

1. Flask 디버그 모드와 PIN 개요

  • 디버그 모드는 개발자가 실시간으로 애플리케이션의 변경 사항을 반영하고, 오류가 발생했을 때 문제를 쉽게 분석할 수 있도록 돕는다.
  • 디버그 모드를 활성화하면 다음과 같은 기능이 제공된다:
    1. 자동 리로드(Automatic Reloading)
      • 소스 코드가 변경되면 서버가 자동으로 다시 실행되어 개발 속도를 높인다.
    2. 인터랙티브 디버거(Interactive Debugger)
      • 오류가 발생하면 Werkzeug Interactive Debugger가 실행되며, 개발자가 애플리케이션 내부 상태를 분석하고 명령어를 실행할 수 있다.
    3. 추적 로그(Traceback Logs)
      • 애플리케이션에서 발생하는 오류를 상세한 스택 트레이스(Stack Trace)와 함께 제공한다.

 

 

1.1 PIN(Personal Identification Number)

  • Flask 디버거는 원격 접속 보호를 위해 PIN을 사용한다.
  • PIN을 입력하면 공격자가 디버거 콘솔을 통해 원격 코드 실행(RCE, Remote Code Execution)을 수행할 수 있다.
  • 이 PIN은 특정 환경 변수 및 시스템 정보를 이용해 자동 생성되며, 이를 추출할 수 있으면 공격자가 디버거에 무단 접근할 수 있다.

 


2. LFI(Local File Inclusion)와 PIN 생성 코드 접근

  • LFI 취약점이 존재하면 서버의 내부 파일을 읽어낼 수 있다.
  • 이를 활용하여 PIN을 생성하는 코드를 확인하고, 실제 디버그 PIN을 계산할 수 있다.

 

2.1 LFI로 버전 정보 및 디버그 코드 접근

  • 다음과 같은 파일들을 LFI로 읽어보면 유용한 정보를 얻을 수 있다.
  1. Python 버전 확인
    • Flask가 사용하는 Werkzeug 버전을 확인하여 디버거 코드가 포함된 위치를 특정할 수 있다.
  2. <http://target.com/view?file=/usr/local/lib/python3.8/site-packages/werkzeug/__init__.py>
  3. Werkzeug Debug PIN 생성 코드 확인
    • 이 파일을 확인하면 get_pin_and_cookie_name() 함수가 포함된 코드를 읽어낼 수 있다.
    • 이 코드를 통해 PIN이 어떤 방식으로 생성되는지 분석 가능하다.
  4. <http://target.com/view?file=/usr/local/lib/python3.8/site-packages/werkzeug/debug/__init__.py>

 


3. PIN 생성 코드 분석

  • Werkzeug의 get_pin_and_cookie_name() 함수는 다음과 같은 절차로 PIN을 생성한다.

 

3.1 PIN 생성에 사용되는 정보

  • PIN은 다음과 같은 정보를 조합하여 생성된다.

 

3.1.1 정보 

  1. username: getpass.getuser()
    • 현재 실행 중인 유저의 이름
  2. modname: app.__module__ 또는 app.__class__.__module__
    • Flask 애플리케이션이 정의된 모듈명
  3. app_name: app.__name__ 또는 app.__class__.__name__
    • Flask 애플리케이션의 클래스 이름
  4. mod.file: sys.modules.get(modname).__file__
    • Flask 모듈 파일 경로
  5. MAC 주소: uuid.getnode()
    • 머신의 네트워크 인터페이스에서 얻은 MAC 주소
  6. 머신 ID: get_machine_id()
    • /etc/machine-id 또는 /proc/sys/kernel/random/boot_id에서 가져옴

 


4. LFI를 활용한 PIN 직접 추출

  • 공격자는 LFI(Local File Inclusion)를 이용하여 아래의 파일을 읽어볼 수 있다.

 

4.1 환경 변수에서 직접 추출 (/proc/self/environ)

<http://target.com/view?file=/proc/self/environ>
  • 환경 변수 중 WERKZEUG_DEBUG_PIN이 포함되어 있을 수 있으며, 예를 들어 다음과 같은 값이 노출될 수 있다.
WERKZEUG_DEBUG_PIN=123-456-789
  • 이 값을 직접 획득하면 디버거에 접근할 수 있다.

 

 

4.2 flask_debug.pickle 파일 확인

  • Werkzeug는 일부 환경에서 디버그 정보를 flask_debug.pickle 파일에 저장할 수 있다.
<http://target.com/view?file=/tmp/flask_debug.pickle>
  • 이 파일을 로컬에서 분석하면 PIN을 포함한 중요한 정보를 획득할 수 있다.

 


5. 직접 PIN을 계산하는 방법

  • 만약 환경 변수에서 PIN을 직접 찾을 수 없다면, LFI를 통해 공개 정보와 비공개 정보를 획득한 후 PIN을 직접 계산할 수도 있다.

5.1 LFI로 필요한 정보 수집

  1. 사용자 이름(username)
    • 시스템 내 사용자 계정을 확인하여 실행 중인 유저를 특정할 수 있다.
    • <http://target.com/view?file=/etc/passwd>
  2. 애플리케이션 모듈명 및 파일 경로
    • <http://target.com/view?file=/usr/local/lib/python3.8/site-packages/my_flask_app/__init__.py>
  3. MAC 주소
    • <http://target.com/view?file=/sys/class/net/eth0/address>
  4. 머신 ID
    • <http://target.com/view?file=/etc/machine-id>

 


6. 결론 및 대응 방안

6.1 공격 가능성 요약

  • LFI 취약점이 존재하면 공격자는 WERKZEUG_DEBUG_PIN을 추출하거나 직접 계산 가능하다.
  • PIN을 탈취하면 원격 코드 실행(RCE)이 가능하므로 매우 위험한 취약점이다.

 

 

6.2 보안 조치

  • Flask 디버그 모드 비활성화 (app.debug = False)
  • 환경 변수에서 WERKZEUG_DEBUG_PIN을 제거
  • LFI 취약점 방어 (파일 접근 검증 및 경로 화이트리스트 적용)
  • 배포 환경에서는 Flask 디버거 사용 금지