무슨 일이 벌어지고 있나
최근 몇 달 사이에 나온 세 개의 별도 보고서가 같은 방향을 가리킵니다.
- Cequence(10월 28일 발표): 하나의 스캐너가 약 32개의 가짜 AI 신원을 사용했고, 최소 9월 말부터 10월 말까지 활동했습니다. 각 클라우드 주소는 약 8초 동안 50~190개의 요청을 몰아서 보낸 뒤 다음으로 넘어갔습니다. 하루에 300개가 넘는 주소를 사용했고, 9월 말의 주소는 한 달 뒤 단 하나도 다시 나타나지 않았습니다. CSO Online은 이런 로테이션 때문에 고정 IP 차단 목록의 효과가 크게 떨어진다고 지적합니다.
- GreyNoise(8월): 다른 클러스터가 824개의 주소에서 13개의 AI 크롤러를 사칭했으며, 그중 어느 주소도 각 회사가 공개한 IP 범위에 속하지 않았습니다. 가장 많이 요청된 경로는 프레임워크가 시크릿을 남길 만한 모든 곳의 체크리스트처럼 보였습니다: /.env, /app/.env, /api/.env, /backend/.env, /.env.local, /.env.production, /.env.bak, /.aws/credentials. 가짜 봇은 /robots.txt를 단 한 번도 요청하지 않았습니다. Anthropic의 진짜 크롤러는 요청했고, 자격 증명 파일은 한 번도 요청하지 않았습니다.
- Symantec(Help Net Security 보도, 10월 23일): 보호되지 않은 AI 서비스로 위장한 허니팟이 공격자의 자율 에이전트가 작동하는 모습을 포착했습니다. 그 탈옥 프롬프트는 .env 파일, API 키, 데이터베이스 스키마를 읽는 것이 평범한 개발 작업이라고 모델에게 말했습니다. 허니팟이 기록한 12만 7,000건 이상의 요청 대부분은 정찰, 훔친 키 시도, 노출된 설정 파일 탐색이었습니다.
패턴은 분명합니다. 공격자들은 사이트 운영자들이 AI 크롤러를 허용 목록에 넣기 시작했다는 것을 알기에 그 이름을 빌립니다. 그리고 AI 키가 실제 돈이 된다는 것도 압니다. 유출된 OpenAI, Anthropic, Gemini 키는 알아차리기 전에 큰 청구서를 만들 수 있습니다.
빠르게 출시하는 개발자가 신경 써야 하는 이유
사용자 에이전트 문자열은 방문자가 자기 자신에 대해 적어 보내는 헤더일 뿐입니다. 아무것도 증명하지 않습니다. 호스팅 설정, CDN 규칙, WAF가 ‘알려진 AI 봇’을 통과시키고 있다면, 바로 이런 트래픽에 문을 열어 준 셈일 수 있습니다.
더 중요한 것은, 노림수가 빠르게 출시된 앱에서 흔히 나오는 실수라는 점입니다. 빌드가 프로젝트 폴더 전체를 복사하는 바람에 .env 파일이 웹 루트에 들어갑니다. 늦은 밤 수정 후 .env.production.bak이 남겨집니다. Docker 이미지가 /app을 정적 파일로 제공합니다. 어느 것도 교묘한 익스플로잇이 필요 없습니다. GET 요청 하나면 되고, 봇에게는 그것이 첫 번째 요청이든 아흔 번째 요청이든 상관없습니다.
내 앱을 확인하는 방법
스캐너가 실제로 요청하는 경로부터 시작하세요. 아래 루프를 내 도메인으로 바꿔 터미널에서 실행합니다.
모든 줄이 404 또는 403이어야 합니다. 200은 문제지만, 당황하기 전에 본문을 확인하세요. 많은 싱글 페이지 앱은 알 수 없는 경로에 대해 index.html을 200으로 반환합니다. curl -s https://yourapp.com/.env | head -5 를 실행해 무엇이 돌아오는지 보세요. KEY=value 형태의 줄이 보인다면 그 파일의 모든 시크릿이 유출된 것으로 간주하세요.
for p in .env .env.local .env.production .env.bak .env.old \
app/.env api/.env backend/.env .aws/credentials .git/config; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://yourapp.com/$p")
echo "$code /$p"
done이왕 하는 김에, 같은 시크릿을 다른 경로로 내주는 관련 유출도 확인하세요:
- 접근 가능한 .git 디렉터리가 있으면 누구나 소스를 재구성할 수 있습니다. 한 번이라도 커밋된 .env도 포함해서요.
- JavaScript 번들 안의 키는 스캐너조차 필요 없습니다. DevTools를 열고 번들에서 sk-, AIza, key를 검색해 보세요.
- 프로덕션의 소스 맵은 주석까지 포함한 원본 소스를 그대로 내보낼 수 있습니다.
그다음 로그를 확인하세요. /.env 나 /.aws/credentials 에 대한 요청을 검색합니다. 그중 하나라도 200을 반환했다면, 그때가 사고의 시작 시점입니다.
해결 방법
1. 시크릿을 웹 루트 밖으로 빼세요. 진짜 해결책은 제공할 파일 자체가 없는 것입니다. 환경 변수는 정적 자산과 함께 배포되는 파일이 아니라 호스트 설정(Vercel, Netlify, Railway, Fly 등 모두 지원합니다)에 있어야 합니다. .env* 가 .gitignore 와 .dockerignore 모두에 포함되어 있는지 확인하세요.
2. 안전장치로 서버에서 닷파일을 차단하세요. nginx의 경우:
# Deny all hidden files except the ACME challenge path
location ~ /\.(?!well-known) {
deny all;
return 404;
}Apache(.htaccess)의 경우:
<FilesMatch "^\.">
Require all denied
</FilesMatch>정적 파일을 제공하는 Express 앱이라면 express.static 은 기본적으로 닷파일을 무시합니다. dotfiles: 'allow' 로 덮어쓰지 마세요.
3. 노출된 것은 모두 교체하세요. 파일을 지운다고 유출된 키가 되돌아오지는 않습니다. 한 번이라도 접근 가능했던 시크릿은 모두 교체하세요. 결제, 데이터베이스, AI 제공업체 키부터 시작하세요. Railway 침해에 관한 글에서 다운타임 없이 앱 시크릿을 교체하는 방법을 단계별로 설명합니다.
4. 사용자 에이전트를 믿지 마세요. 방화벽이나 속도 제한에서 AI 크롤러를 통과시킨다면, 이름으로 비교하지 말고 각 회사가 공개한 IP 범위로 검증하세요. GreyNoise는 보고서에서 Anthropic, OpenAI, Google, Perplexity의 공식 JSON 파일을 안내합니다. Cequence의 조언도 같습니다. 서명된 요청, 공개된 주소 범위, 또는 직접 연동으로 검증하라는 것입니다.
5. 노출된 개발 도구는 패치하세요. GreyNoise는 이 스캐너들이 Vite 파일 읽기 버그 CVE-2025-30208을 시도하는 것도 확인했습니다. Vite 개발 서버가 인터넷에서 접근될 가능성이 있다면 6.2.3, 6.1.2, 6.0.12, 5.4.15 또는 4.5.10 이상으로 업그레이드하고, 애초에 개발 서버를 공개하지 마세요.
6. AI 키에 지출 한도를 설정하세요. 대부분의 AI 제공업체는 월 지출 상한을 두거나 키를 특정 프로젝트로 제한할 수 있게 해 줍니다. 유출을 막지는 못하지만, 수천 달러짜리 깜짝 청구서를 작은 금액으로 줄여 줍니다.
빠른 체크리스트
터미널을 닫기 전에 다음을 확인하세요:
- 위 curl 루프의 모든 경로가 파일이 아니라 404/403을 반환한다.
- .env* 가 .gitignore 와 .dockerignore 에 포함되어 있다.
- 서버나 호스트가 닷파일을 거부한다.
- JS 번들이나 소스 맵에 시크릿 키가 없다.
- 한 번이라도 접근 가능했던 키는 모두 교체했다.
- AI 크롤러 허용 목록이 사용자 에이전트만이 아니라 IP 범위를 확인한다.
- AI 제공업체 키에 지출 한도가 설정되어 있다.
봇보다 먼저 확인하세요
이 스캐너들은 수백 개의 주소를 번갈아 쓰고, 한 번의 버스트에 약 8초를 씁니다. 로그를 지켜보는 것으로는 이길 수 없습니다. 이기는 방법은 그들이 문을 두드렸을 때 아무것도 없게 만드는 것입니다.
AppSafe는 바로 이 봇들이 찾아다니는 유출을 검사합니다. 접근 가능한 .env 파일, 노출된 .git 디렉터리, 데이터베이스 덤프, 프런트엔드 번들 속 API 키 등이 포함되며, 모든 발견 항목에는 AI 코딩 도구에 그대로 붙여 넣을 수 있는 수정 프롬프트가 함께 제공됩니다. 아직 출시 전이라면 AI로 만든 앱을 위한 체크리스트도 함께 읽어 보세요. 무료 스캔을 실행해 봇에게 무엇이 보이는지 확인해 보세요.
