Databricks에서는 우리의 AI Red Team이 새로운 소프트웨어 패러다임이 예상치 못한 보안 위험을 어떻게 도입할 수 있는지를 정기적으로 탐색합니다. 우리가 최근에 밀접하게 추적하고 있는 추세 중 하나는 "vibe coding"이라는, 생성 AI를 빠르고 캐주얼하게 사용하여 코드를 구축하는 것입니다. 이 방법은 개발을 가속화시키지만, 또한 미묘하고 위험한 취약점을 도입할 수 있으며, 이는 너무 늦게까지 눈치채지 못하는 경우가 많습니다.
이 글에서는 우리의 레드팀 활동에서 얻은 실제 예시를 통해 바이브 코딩이 어떻게 심각한 취약점을 초래할 수 있는지 살펴봅니다. 또한 이러한 위험을 완화할 수 있는 실천 방법을 제시합니다.
vibe coding 위험성을 탐색하는 초기 실험 중 하나에서, 우리는 Claude에게 사용자가 마우스를 사용하여 위에서 보는 카메라 시점에서 뱀을 제어하는 세 번째 인물 뱀 전투 아레나를 만들라고 요청했습니다. vibe-coding 방법론에 따라, 우리는 모델에 프로젝트의 구조에 대한 상당한 제어권을 허용하고, 각 구성 요소를 생성하도록 점진적으로 요청했습니다. 비록 결과적으로 생성된 애플리케이션은 의도한 대로 작동했지만, 이 과정은 심각한 보안 취약점을 우연히 도입했고, 이를 검사하지 않으면 임의의 코드 실행으로 이어질 수 있었습니다.
뱀 게임의 네트워크 계층은 Python 객체를 pickle을 사용하여 직렬화하고 역직렬화하며, 이 모듈은 임의의 원격 코드 실행 (RCE)에 취약하다고 알려져 있습니다. 결과적으로, 악의적인 클라이언트 또는 서버는 임의의 코드를 실행하는 페이로드를 만들어 게임의 다른 인스턴스에서 보낼 수 있습니다.
아래의 코드는 Claude가 생성한 네트워크 코드에서 직접 가져온 것으로, 네트워크에서 받은 객체가 검증이나 보안 검사 없이 직접 역직렬화되는 문제를 명확하게 보여줍니다.
이런 종류의 취약점은 고전적이고 잘 문서화되어 있지만, vibe 코딩의 특성상 생성된 코드가 "그냥 작동"하는 것처럼 보일 때 잠재적인 위험을 간과하기 쉽습니다.
그러나 클로드에게 코드를 안전하게 구현하도록 요청함으로써, 우리는 모델이 다음과 같은 보안 문제를 적극적으로 식별하고 해결하는 것을 관찰했습니다:
아래 코드 발췌문에서 볼 수 있듯이, 이 문제는 데이터 직렬화를 위해 pickle에서 JSON으로 전환함으로써 해결되었습니다. 서비스 거부 공격을 방지하기 위해 크기 제한도 도입되었습니다.
다른 실험에서, 우리는 ChatGPT에게 GGUF 이진 형식에 대한 파서를 생성하도록 요청했는데, 이 형식은 안전하게 파싱하기 어렵다고 널리 인식되고 있습니다. GGUF 파일은 C와 C++로 구현된 모듈에 대한 모델 가중치를 저장하며, 우리는 이 형식을 Databricks가 공식 GGUF 라이브러리에서 여러 취약점을 발견한 적이 있기 때문에 특별히 선택했습니다.
ChatGPT는 파일 파싱과 메타데이터 추출을 올바르게 처리하는 작동 구현을 빠르게 만들었으며, 이는 아래의 소스 코드에서 확인할 수 있습니다.
그러나 더 자세히 살펴보니, 안전하지 않은 메모리 처리와 관련된 중요한 보안 결함을 발견했습니다. 생성된 C/C++ 코드에는 확인되지 않은 버퍼 읽기와 형식 혼동의 사례가 포함되어 있었으며, 이들은 모두 악용될 경우 메모리 손상 취약점을 초래할 수 있습니다.
이 GGUF 파서에서는 검사되지 않은 입력과 안전하지 않은 포인터 산술로 인해 여러 메모리 손상 취약점 이 존재합니다. 주요 문제점은 다음과 같습니다:
공격자는 가짜 헤더, 키 또는 값 필드에 대한 매우 크거나 음수의 길이, 그리고 임의의 페이로드 데이터를 가진 GGUF 파일을 조작하여 이 문제 중 두 번째를 악용할 수 있습니다. 예를 들어, 키 길이가 0xFFFFFFFFFFFFFFFF (최대 부호 없는 64비트 값)인 경우, 검사되지 않은 malloc() 이 작은 버퍼를 반환하지만, 이후 memcpy() 는 여전히 그 이후에 쓰여서 전형적인 힙 기반 버퍼 오버플로우를 일으킵니다. 마찬가지로, 파서가 유효한 문자열이나 배열 길이를 가정하고 메모리에 읽어들이는데 사용 가능한 공간을 검증하지 않으면 메모리 내용이 유출될 수 있습니다. 이런 결함들은 임의의 코드 실행을 달성하는 데 사용될 수 있습니다.
이 문제를 검증하기 위해, 우리는 ChatGPT에 악의적인 GGUF 파일을 생성하고 취약한 파서에 전달하는 증거 개념을 생성하도록 요청했습니다. 결과 출력은 프로그램이 매핑된 메모리 페이지의 끝에 도달하고 그 이후에 매핑되지 않은 페이지에 쓰려고 할 때, 경계를 벗어난 메모리 접근으로 인해 세그멘테이션 오류를 일으키며, 이는 memmove 함수 내에서 프로그램이 충돌하는 것을 보여줍니다. 프로그램이 매핑된 메모리 페이지의 끝에 도달하고 그 이후의 매핑되지 않은 페이지에 쓰려고 할 때 충돌이 발생합니다. 이는 경계를 벗어난 메모리 접근으로 인해 세그멘테이션 오류를 유발합니다.
다시 한번 우리는 ChatGPT에게 코드를 수정하는 데 대한 제안을 요청했고, 그것은 다음과 같은 개선 사항을 제안할 수 있었습니다:
그런 다음 우리는 업데이트된 코드를 가져와서 개념 증명 GGUF 파일을 전달했고, 코드는 변형된 레코드를 감지했습니다.
다시 말해, 핵심 문제는 ChatGPT가 기능적인 코드를 생성하는 능력이 아니라, 바이브 코딩에 내재된 캐주얼한 접근 방식이 생성된 구현에서 위험한 가정을 눈치채지 못하게 했다는 것입니다.
보안 전문가가 코드를 검토하여 취약점이 없는지 확인하는 것에 대한 대체제는 없지만, vibe 코딩 세션 동안 위험을 완화하는데 도움이 될 수 있는 몇 가지 실용적이고 소요 시간이 적은 전략들이 있습니다. 이 섹션에서는 코드의 보안성을 크게 향상시킬 수 있는 세 가지 간단한 방법을 설명합니다. 이 게시물에 제시된 각 프롬프트는 ChatGPT를 사용하여 생성되었음을 보여주며, 이는 어떤 바이브 코더라도 광범위한 보안 전문 지식 없이도 효과적인 보안 지향적 프롬프트를 쉽게 생성할 수 있음을 보여줍니다.
첫 번째 방법은 일반적인, 보안 중심의 시스템 프롬프트를 사용하여 LLM을 처음부터 안전한 코딩 행동으로 유도하는 것입니다. 이러한 프롬프트는 기본 보안 지침을 제공하여 생성된 코드의 안전성을 향상시킬 수 있습니다. 우리의 실험에서는 다음과 같은 프롬프트를 사용했습니다:
프로그래밍 언어나 애플리케이션 컨텍 스트가 미리 알려져 있을 때, 다른 효과적인 전략은 LLM에 맞춤형, 언어 특정 또는 애플리케이션 특정 보안 프롬프트를 제공하는 것입니다. 이 방법은 직접적으로 작업에 관련된 알려진 취약점이나 일반적인 함정을 대상으로 합니다. 눈에 띄는 것은, 이러한 취약성 클래스를 명시적으로 인식할 필요조차 없다는 것입니다. 왜냐하면 LLM 자체가 적절한 시스템 프롬프트를 생성할 수 있기 때문입니다. 우리의 실험에서, 우리는 ChatGPT에 다음의 요청을 사용하여 언어별 프롬프트를 생성하도록 지시했습니다:
세 번째 방법은 코드 생성 직후에 자기 반성적인 검토 단계를 포함하는 것입니다. 처음에는 특정 시스템 프롬프트를 사용하지 않지만, LLM이 코드 구성 요소를 생성하면 출력이 모델로 다시 입력되어 보안 취약점을 명확하게 식별하고 해결합니다. 이 접근법은 모델의 내재된 능력을 활용하여 처음에 놓칠 수 있는 보안 문제를 감지하고 수정하는 데 사용됩니다. 우리의 실험에서는 원래의 코드 출력을 사용자 프롬프트로 제공하고 다음 시스템 프롬프트를 사용하여 보안 검토 과정을 안내했습니다:
각 프롬프팅 접근법의 효과를 정량적으로 평가하기 위해, 우리는 PurpleLlama의 사이버보안 벤치마크 테스트 스위트에서 보안 코딩 벤치마크를 사용하여 실험을 진행했습니다. 이 벤치마크에는 vibe 코딩 워크플로우와 직접적으로 관련된 시나리오에서 LLM이 안전하지 않은 코드를 생성하는 경향을 측정하기 위해 설계된 두 가지 유형의 테스트가 포함되어 있습니다.
이 두 시나리오를 모두 테스트하는 것은 특히 유용합니다. 왜냐하면, 일반적인 vibe 코딩 세션 동안 개발자들은 종종 먼저 모델에게 코드를 생성하도록 지시한 다음, 문제를 해결하기 위해 이 코드를 모델에 다시 붙여넣는 것이므로, 이는 지시와 자동완성 시나리오를 밀접하게 반영하기 때문입니다. 우리는 Claude 3.7 Sonnet과 GPT 4o 두 모델을 Secure Coding Benchmark에 포함된 모든 프로그래밍 언어에서 평가했습니다. 다음 플롯은 시스템 프롬프트가 없는 기준 시나리오에 비해 각각의 세 가지 프롬프팅 전략에 대한 취약한 코드 생성률의 백분율 변화를 보여줍니다. 음수 값은 개선을 나타내며, 이는 프롬프트 전략이 불안전한 코드 생성률을 줄였음을 의미합니다.
Claude 3.7 Sonnet으로 코드를 생성할 때, 제공된 세 가지 프롬프트 전략 모두 개선을 가져왔지만, 그 효과는 크게 달랐습니다:
