프로젝트 구조
cat << EOF > setup.sh
sudo mkdir -p /usr/local/lib/docker/cli-plugins/
sudo curl -SL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
docker compose version
EOF
chmod +x setup.sh
./setup.sh
Shell
복사
cp product/product project/product
cp user/user project/user
cp stress/stress project/stress
Shell
복사
export AWS_REGION=ap-northeast-2
export AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY_ID>
export AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY>
Shell
복사
cd project
docker compose up -d
Shell
복사
정상 요청 테스트
user
curl -X POST http://localhost:8081/v1/user \
-H "Content-Type: application/json" \
-d '{"requestid":"999","uuid":"7c5a3c6a-758f-4bc5-9bdf-3e573a0ad729","username":"dbdump500001","email":"dbdump500001@example.org","status_message":"I’m happy"}'
Shell
복사
USER POST Request
curl -X GET "http://localhost:8081/v1/user?email=dbdump500001@example.org&requestid=999999999999&uuid=7c5a3c6a-758f-4bc5-9bdf-3e573a0ad729"
Shell
복사
USER GET Request
product
curl -X POST http://localhost:8082/v1/product \
-H "Content-Type: application/json" \
-d '{"requestid":"999999999999","uuid":"7c5a3c6a-758f-4bc5-9bdf-3e573a0ad729","id":"dbdump500001","name":"dbdump500001","price":1234}'
Shell
복사
PRODUCT POST Request
curl -X GET "http://localhost:8082/v1/product?id=dbdump500001&requestid=999999999999&uuid=7c5a3c6a-758f-4bc5-9bdf-3e573a0ad729"
Shell
복사
PRODUCT GET Request
stress
curl -X POST http://localhost:8083/v1/stress \
-H "Content-Type: application/json" \
-d '{"requestid":"999","uuid":"7c5a3c6a-758f-4bc5-9bdf-3e573a0ad729","length":256}'
Shell
복사
STRESS POST Request
curl -X GET http://localhost:8081/healthcheck
curl -X GET http://localhost:8082/healthcheck
curl -X GET http://localhost:8083/healthcheck
Shell
복사
Healthcheck
비정상 요청 테스트
cat << EOF > bad_requests.py
#!/usr/bin/env python3
import requests
import json
apps = {
"user": "http://localhost:8081/v1/user",
"product": "http://localhost:8082/v1/product",
"stress": "http://localhost:8083/v1/stress",
}
# 비정상 요청 샘플
bad_requests = [
# ===== user =====
{
"app": "user",
"desc": "email 형식 오류 (도메인 없음)",
"url": apps["user"],
"data": {"requestid": "1", "uuid": "uuid-001", "username": "test", "email": "gildong", "status_message": "Hello"}
},
{
"app": "user",
"desc": "email 형식 오류 (도메인 형식 오류)",
"url": apps["user"],
"data": {"requestid": "2", "uuid": "uuid-002", "username": "test", "email": "gildong@example", "status_message": "Hello"}
},
{
"app": "user",
"desc": "uuid 형식 잘못됨",
"url": apps["user"],
"data": {"requestid": "3", "uuid": "baduuid", "username": "test", "email": "gildong@example.org", "status_message": "Hello"}
},
{
"app": "user",
"desc": "XSS 공격",
"url": apps["user"],
"data": {"requestid": "4", "uuid": "uuid-xss", "username": "<script>alert(1)</script>", "email": "xss@example.org", "status_message": "Hello"}
},
{
"app": "user",
"desc": "SQL Injection",
"url": apps["user"],
"data": {"requestid": "5", "uuid": "uuid-sqli", "username": "test'; DROP TABLE users; --", "email": "sql@example.org", "status_message": "Hello"}
},
{
"app": "user",
"desc": "GET 요청에 Body 포함",
"url": apps["user"],
"data": {"requestid": "6", "uuid": "uuid-getbody", "username": "getbody", "email": "getbody@example.org", "status_message": "Hello"},
"method": "GET"
},
{
"app": "user",
"desc": "status_message 비정상 문자열",
"url": apps["user"],
"data": {"requestid": "7", "uuid": "uuid-badmsg", "username": "test", "email": "test@example.org", "status_message": "I'm bad <script>alert(1)</script>"}
},
{
"app": "user",
"desc": "username에 'admin' 넣어서 요청 (권한 우회 테스트)",
"url": apps["user"],
"data": {"requestid": "8", "uuid": "uuid-admin", "username": "admin", "email": "admin@example.org", "status_message": "Hello"}
},
{
"app": "user",
"desc": "status_message에 이상한 문자(널, ANSI 시퀀스, 이모지, SVG 인젝션)",
"url": apps["user"],
"data": {
"requestid": "9",
"uuid": "uuid-weird",
"username": "weird",
"email": "weird@example.org",
# \u0000 (널), \x1b ANSI 색상 시퀀스, 이모지, 그리고 간단한 SVG 인젝션 패턴 포함
"status_message": "Weird chars:\u0000\x1b[31mRED\x1b[0m 😀🚫 <svg/onload=alert(1)>"
}
},
# ===== product =====
{
"app": "product",
"desc": "price INT 범위 초과",
"url": apps["product"],
"data": {"requestid": "101", "uuid": "uuid-prod1", "id": "p1", "name": "prod1", "price": 999999999999999999999}
},
{
"app": "product",
"desc": "price 문자열",
"url": apps["product"],
"data": {"requestid": "102", "uuid": "uuid-prod2", "id": "p2", "name": "prod2", "price": "onehundred"}
},
{
"app": "product",
"desc": "User-Agent 봇",
"url": apps["product"],
"data": {"requestid": "103", "uuid": "uuid-prod3", "id": "p3", "name": "prod3", "price": 100},
"headers": {"User-Agent": "bot-attack"}
},
# ===== stress =====
{
"app": "stress",
"desc": "requestid/uuid 누락",
"url": apps["stress"],
"data": {"length": 256}
},
{
"app": "stress",
"desc": "Content-Type 오류",
"url": apps["stress"],
"data": '{"requestid":"201","uuid":"uuid-s1","length":256}',
"headers": {"Content-Type": "text/plain"}
},
]
def send_request(req):
method = req.get("method", "POST").upper()
headers = req.get("headers", {"Content-Type": "application/json"})
data = req["data"]
url = req["url"]
app = req.get("app", "unknown")
desc = req.get("desc", "")
requestid = ""
uuid = ""
# data가 dict인 경우에만 requestid/uuid 접근
if isinstance(data, dict):
requestid = data.get("requestid", "")
uuid = data.get("uuid", "")
try:
if method == "POST":
# Content-Type이 application/json이면 json= 사용, 아니면 data= 사용
if isinstance(data, dict) and headers.get("Content-Type") == "application/json":
resp = requests.post(url, json=data, headers=headers, timeout=5)
else:
resp = requests.post(url, data=data, headers=headers, timeout=5)
elif method == "GET":
resp = requests.get(url, params=data if isinstance(data, dict) else None, headers=headers, timeout=5)
else:
print(f"[{app}] Unsupported method: {method}")
return
body_preview = resp.text[:100] + ("..." if len(resp.text) > 100 else "")
print(f"[{app}] {desc}\n requestid={requestid}, uuid={uuid}, method={method}, status={resp.status_code}, response={body_preview}\n")
except Exception as e:
print(f"[{app}] {desc}\n requestid={requestid}, uuid={uuid}, method={method}, ERROR={e}\n")
# 실행
for req in bad_requests:
send_request(req)
EOF
Shell
복사
python3 bad_requests.py
Shell
복사
