요즘IT
위시켓
최근 검색어
전체 삭제
최근 검색어가 없습니다.

이전 글 ‘개발과 보안 통합 ‘데브섹옵스’ 중요해지는 이유’에서 데브섹옵스의 개념과 이를 위한 오픈소스 보안 테스트 자동화 도구를 다뤘습니다. 크게 정적 보안 테스팅(SAST), 동적 보안 테스팅(DAST), 소프트웨어 구성요소(SCA) 분야별로 도구를 간단히 소개했는데요. 이번 글에서는 Bandit 예제와 함께 정적 보안 테스팅에 대해 좀 더 자세히 알아보겠습니다.

회원가입을 하면 원하는 문장을
저장할 수 있어요!

다음

회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!

확인

개발

데브섹옵스 실현을 위한 '정적 보안 테스팅(SAST)'

년차,
어떤 스킬
,
어떤 직무
독자들이 봤을까요?
어떤 독자들이 봤는지 궁금하다면?
로그인
<출처: 작가>

 

이전 글 ‘개발과 보안 통합 ‘데브섹옵스’ 중요해지는 이유’에서 데브섹옵스의 개념과 이를 위한 오픈소스 보안 테스트 자동화 도구를 다뤘습니다. 크게 정적 보안 테스팅(SAST), 동적 보안 테스팅(DAST), 소프트웨어 구성요소(SCA) 분야별로 도구를 간단히 소개했는데요. 이번 글에서는 Bandit 예제와 함께 정적 보안 테스팅에 대해 좀 더 자세히 알아보겠습니다.

 

정적 보안 테스팅(SAST)

정적 보안 테스팅은 소스 코드를 분석하여 SQL 인젝션, 크로스 사이트 스크립팅(XSS), 원격 코드 실행 취약점, 권한 오용 문제 등 잠재적인 보안 취약점을 식별하는 테스트 방법입니다. 실제 프로그램을 실행하지 않고 코드만을 분석하여 테스트를 수행하기 때문에 정적(static)이라는 용어를 사용합니다. 정적 보안 테스팅의 주요 장점은 다음과 같습니다.

 

장점 1) 개발 초기 단계에서 취약점 발견

정적 보안 테스팅은 소스 코드를 검사하므로, 소스 코드가 작성되는 소프트웨어 개발 초기 단계에서부터 보안 문제를 검사하고 발견할 수 있습니다. 이를 통해 개발 후반부나 운영 단계에서 취약점을 발견했을 때보다 들어갈 비용과 노력을 줄일 수 있습니다. 잠시 후 실습으로 잠재적인 데이터 유출 위험을 초기에 차단할 수 있는 예시를 알아보겠습니다. SQL 인젝션 취약점이 있는 코드를 검사하여 문제를 발견하는 사례를 준비했습니다.

 

장점 2) 높은 코드 커버리지

정적 보안 테스팅은 실제 실행 환경과 무관하게 소스코드를 검사합니다. 따라서 이론적으로 모든 실행 경로를 테스트하여 높은 코드 커버리지를 달성할 수 있습니다. 예를 들어, 복잡한 분기 로직이 있는 애플리케이션에서도 정적 보안 테스팅은 가능한 모든 경로를 탐색하여 취약점을 찾아낼 수 있습니다. 동적 보안 테스팅의 경우는 코드 진행 경로를 테스트 과정에서 놓친다면, 특정 코드를 테스트하지 못하는 경우가 발생할 수 있습니다.

 

장점 3) 검사 환경 용이성

정적 보안 테스팅은 실제 애플리케이션을 실행하지 않고 소스 코드만으로 분석을 진행합니다. 따라서 특정 운영 환경에 구애받지 않습니다. 코드만 있다면 어디서든 테스트할 수 있어 별도의 서버 리소스가 필요 없고, 깃과 같은 코드 저장소에서도 쉽게 검사를 수행할 수 있어 자동화가 수월합니다.

 

다만 이러한 정적 보안 테스팅에도 몇 가지 단점이 존재합니다.

 

단점 1) 오탐(False Positive) 문제

정적 보안 테스팅 도구는 복잡한 코드 패턴을 잘못 해석하여 실제로는 문제가 발생하지 않는 코드를 보안 취약점으로 잘못 감지할 수 있습니다. 오탐은 불필요한 노이즈를 발생시켜 문제 대응에 대한 초점을 분산시키고 생산성을 떨어뜨릴 수 있습니다. 특히 이런 오탐 문제는 일반적으로 동적 보안 테스팅보다 정적 보안 테스팅에서 더 많이 발생합니다. 아래 실습에서 오탐 문제를 좀 더 자세히 살펴보겠습니다.

 

단점 2) 미탐(False Negative) 문제

코드를 분석하는 정적 분석 방식의 한계로 인해 특정 유형의 취약점을 탐지하지 못하는 문제도 있습니다. 런타임에서 설정이 잘못되어 발생하는 문제나 외부 데이터에 의존적인 취약점은 발견하기 어렵습니다. 예를 들어, 외부 데이터베이스나 파일 시스템에 대한 권한 부여 설정이 허술해 발생하는 데이터 유출 문제는 정적 보안 테스팅으로 검사하기 어렵습니다. 애플리케이션 코드 외부에서 이루어지는 문제이기 때문입니다. 일부 중요한 웹 보안 기능(예: HTTPS 적용, CSRF 토큰 사용, 웹 보안 헤더 등) 설정과 관련해 생기는 문제 역시 탐지할 수 없습니다.

 

 

정적 보안 테스팅 도구 실습

지금까지 정적 보안 테스팅에 대해 간단히 알아보았습니다. 이제 정적 보안 테스팅을 직접 실습하며 자세한 내용을 알아보겠습니다. 이번 실습에는 파이썬 언어로 작성된 프로젝트의 보안 취약점을 검사할 수 있는 오픈소스 도구, Bandit를 사용합니다. 

 

SQL 인젝션 취약점 코드 예제

실습을 위해 SQL 인젝션 취약점이 존재하는 간단한 파이썬 코드를 준비했습니다.

1 import sqlite3
2 
3 # DB 연결
4 conn = sqlite3.connect('example.db')
5 c = conn.cursor()
6 
7 # 테이블 생성
8 def init_db():
9     c.execute('''CREATE TABLE IF NOT EXISTS users
10                  (id INTEGER PRIMARY KEY, name TEXT, password TEXT)''')
11 
12     c.execute("INSERT INTO users (name, password) VALUES ('alice', 'password123')")
13     c.execute("INSERT INTO users (name, password) VALUES ('bob', 'qwerty456')")
14 
15 # 사용자 조회 함수 (취약점 있음)
16 def get_user(user_id):
17     query = "SELECT name, password FROM users WHERE id={}".format(user_id)
18     c.execute(query)
19     return c.fetchall()
20     
21 # query를 실행하지 않는 함수
22 def do_nothing(user_id):
23     query = "SELECT name, password FROM users WHERE id={}".format(user_id)
24     
25 if __name__ == "__main__":
26     init_db()
27     user_id = input("Enter user ID: ")
28     user = get_user(user_id)
29     if user:
30         print(user)
31     else:
32         print("User not found")

 

코드는 다음과 같이 구성되어 있습니다.

  • 줄번호 3-5: sqlite DB 파일 생성 및 연결
  • 줄번호 7-13: init_db() 함수 정의 ; 테이블 생성 및 alice, bob 사용자 추가
  • 줄번호 15-19: get_user() 함수 정의 ; user_id 입력 값으로 SELECT 쿼리문을 구성하고 실행하여, 조건에 맞는 사용자를 검색 (SQL 인젝션 취약점이 존재함)
  • 줄번호 21-23: do_nothing() 함수 정의 ; SELECT 쿼리문을 구성하지만 실행은 하지 않음 (오탐 문제를 설명하기 위해 추가된 함수)
  • 줄번호 25-32: 프로그램이 실행되면 실행되는 main 파트

 

이 코드를 실행하면 아래와 같은 순서로 진행됩니다.

  • 줄번호 26: init_db() 함수에서 sqlite3를 사용하여 간단한 사용자 데이터베이스를 구축
  • 줄번호 27: 사용자 ID 를 입력받음
  • 줄번호 28, 17-18: get_user() 함수에서 SELECT 쿼리문을 실행하여, 사용자(user)를 검색
  • 줄번호 29-32: 사용자 정보 출력

 

코드를 sqli-example.py라는 이름으로 저장하고 실행해 보겠습니다.

% python3 sqli-example.py  

*%는 macOS 터미널의 프롬프트를 표시합니다. 리눅스의 경우 $가 대신 표시됩니다.

 

코드를 실행한 다음 user ID의 입력값으로 1을 넣어 보겠습니다. alice라는 사용자가 출력됩니다. 2를 입력하면 bob이 출력됩니다. 정상적인 동작입니다.

% python3 sqli-example.py      
Enter user ID: 1
[('alice', 'password123')]

% python3 sqli-example.py
Enter user ID: 2
[('bob', 'qwerty456')]

 

SQL 인젝션 취약점

이때, user ID 입력값을 1 or 1=1 이라고 넣어 보겠습니다.

% python3 sqli-example.py
Enter user ID: 1 or 1=1
[('alice', 'password123'), ('bob', 'qwerty456')]

 

alice와 bob이 모두 출력된 것을 볼 수 있습니다. 현재 데이터베이스에 alice와 bob의 정보만 들어있기 때문에 두 사용자 정보가 출력된 것입니다. 만약 데이터베이스에 사용자 정보가 더 있었다면, 모든 사용자의 정보가 출력되었을 것입니다.

 

앞서 코드의 17번 줄을 보겠습니다. user_id 변수값을 WHERE 조건문에 직접 입력을 하여 쿼리문을 실행하도록 되어 있습니다. 여기서 문제가 발생합니다.

17     query = "SELECT name, password FROM users WHERE id={}".format(user_id)
18     c.execute(query)

 

1 대신 ‘1 or 1=1’이라고 입력하면, 사용자 입력값에 의해 쿼리문이 변형되어 버립니다. 개발자가 기대한 쿼리문은 이럴 것입니다.

SELECT name, password FROM users WHERE id=1

 

그러나 실제 입력값에 따라 변형된 쿼리문은 이렇습니다.

SELECT name, password FROM users WHERE id=1 or 1=1

 

이렇게 변형된 쿼리문에서는 WHERE 조건이 id 값과 상관 없이 항상 참이 됩니다. 그래서 모든 id의 결과가 출력된 것입니다. 이처럼 SQL 인젝션 취약점이 존재하면 데이터베이스 개인정보가 유출되는 사고로 이어질 수 있습니다. 수백만, 수천만 명의 사용자 정보가 탈취되는 대형 사고가 벌어질 가능성이 있는 것이죠.

 

SQL 인젝션 취약점 해결 방법

이러한 SQL 인젝션 문제를 해결하기 위해 파라미터화된 쿼리를 사용합니다. 줄 번호 17-18번의 코드처럼 user_id 를 직접 WHERE 구문에 입력하여 쿼리문을 구성하는 대신, 아래와 같이 ‘?’로 자리를 만들어두고 execute()할 때 user_id를 파라미터로 전달하는 방식입니다. 파라미터를 튜플로 구성해야 하므로 (user_id)대신 (user_id,)와 같이 쉼표(,)를 추가한 점을 유의해야 합니다.

    query = "SELECT name, password FROM users WHERE id=?"
    c.execute(query, (user_id,))

 

이렇게 하면 사용자 입력값이 쿼리문 자체에는 영향을 주지 않아 SQL 인젝션 취약점을 제거할 수 있습니다. 코드를 변경하고 ‘1 or 1=1’ 값으로 실행해 보겠습니다. 이번에는 입력값 전체를 하나의 값으로 처리하여 ID와 비교하게 될 겁니다. 따라서 사용자 정보 대신 ‘User not found’ 문구가 출력됩니다.

% python3 sqli-example.py
Enter user ID: 1 or 1=1
User not found

 

 

Bandit 실습하기

Bandit는 파이썬 언어로 작성된 코드에서 다양한 보안 문제를 발견하기 위한 정적 보안 테스팅 도구입니다. 오픈스택(오픈소스 인프라 클라우드 프로젝트)의 보안 프로젝트로 시작하여, 현재는 아래 링크의 깃허브 프로젝트에서 오픈 소스로 개발되고 있습니다. 위의 예제 코드를 대상으로, 정적 보안 테스팅 도구 Bandit를 이용해 보안 취약점을 검사하는 과정을 실습해 보겠습니다.

 

 

1) Bandit 설치하기

Bandit는 여느 파이썬 프로그램처럼 ‘pip install’ 을 이용해 설치할 수 있습니다.

% python3 -m venv venv
% source venv/bin/activate
(venv) % pip install bandit

 

venv 모듈은 파이썬 가상화 환경을 만들어줍니다. 이를 통해 전체 시스템에 영향을 주지 않고 Bandit를 설치할 수 있습니다. “source venv/bin/activate” 명령어를 실행하여 venv 환경에 진입하였고, 프롬프트 앞에 (venv) 가 표시되는 점을 참고하세요.

 

2) 검사하기

검사 명령어는 다음과 같이 ‘bandit <파일이름>’ 으로 간단히 실행할 수 있습니다.

(venv) % bandit sqli_example.py

 

아래는 Bandit를 통해 예제 코드를 검사한 결과입니다. 두 가지 결과가 보고되었습니다. 그 중 첫 번째로, 우리가 앞서 살펴본 줄번호 17번의 SQL 인젝션 취약점이 발견되었습니다.

 

Bandit 검사 결과 <출처: 작가>

 

오탐 문제

그런데 두 번째 결과를 보니 줄번호 23번에서도 SQL 인젝션 취약점을 찾았다는 내용이 있습니다.

21 # query를 실행하지 않는 함수
22 def do_nothing(user_id):
23     query = "SELECT name, password FROM users WHERE id={}".format(user_id)
24

 

이 경우는 앞선 경우와 다릅니다. 이 함수는 앞서 함수의 줄번호 18번처럼 execute()를 실행하지 않아, 실제로 쿼리문이 실행되지 않습니다. 23번 줄만 봤을 때는 보안 취약점이 있는 것이 맞지만, 이 코드가 실제로 실행되지 않기 때문에 문제가 발생하지는 않습니다. 이처럼 실제로 문제가 되지 않는데 문제가 있다고 보고하는 것을 ‘오탐이 발생했다’고 합니다.

 

이 예제에서는 코드가 간단하기 때문에 오탐 문제가 있어도 쉽게 처리할 수 있습니다. 그러나 규모가 큰 프로젝트의 코드를 대상으로 검사를 진행하면 이러한 오탐 보고가 수백수천 건이 나오기도 합니다. 오탐으로 인한 노이즈가 많아지면 보안 담당자나 개발자들이 이를 분석하느라 시간을 낭비하게 됩니다. 이는 커다란 생산성 저하로 이어집니다. 중요한 취약점이 오탐 보고들에 묻혀 발견되지 않을 수도 있습니다.

 

따라서 정적 보안 테스팅 도구를 효과적으로 활용하기 위해서는 오탐을 최소화하는 것이 매우 중요합니다. 오탐율은 기업에서 정적 보안 테스팅 도구를 도입하기 위해 여러 솔루션을 비교하며 확인하는 중요한 척도입니다. 

 

그뿐만 아니라 특정 도구를 도입한 이후에도 오탐을 줄이기 위한 노력이 필요합니다. 해당 도구의 검사 규칙(또는 룰셋)을 프로젝트 특성에 맞게 잘 구성하고 각 프로젝트에 맞는 예외 규칙을 관리해야 합니다. 또한 발견된 보안 취약점을 검토하고 이를 토대로 오탐을 걸러내는 작업이 필수적입니다. 이런 과정을 체계적으로 수행하는 것이 정적 보안 테스팅 도구 활용의 핵심 요소라고 할 수 있습니다.

 

Bandit 추가 사용 예시

오탐 문제 외에도 정적 보안 테스팅 자동화 관련 고려해야 할 사항이 있습니다. 다만 그에 앞서 Bandit 실습을 진행한 만큼, 이 도구의 몇 가지 사용 예시를 추가로 알아보겠습니다.

 

1) 전체 프로젝트 검사하기

앞서 실습은 파일 하나를 검사한 결과입니다. 전체 프로젝트를 검사하려면 -r 옵션과 함께 프로젝트가 있는 경로를 입력하면 됩니다. -r 옵션을 이용하면 모든 하위 디렉토리까지 한 번에 검사할 수 있습니다.

% bandit -r /path/to/project

 

2) 결과를 JSON, XML, CSV 등 포맷으로 출력

-f 옵션을 사용하면 검사 결과를 특정 포맷으로 출력할 수 있습니다.

% bandit -r /path -f json

 

3) 도움말 기능

-h 옵션을 사용하면 쓸 수 있는 여러 옵션들에 대한 도움말이 출력됩니다.

% bandit -h

 

이 밖에도 Bandit는 다양한 옵션을 제공하며, YAML 포맷의 설정 파일을 사용하여 다양한 옵션과 프로파일을 설정할 수도 있습니다. 자세한 내용은 프로젝트 공식 문서를 참고하세요.

 

 

정적 보안 테스팅 자동화 및 고려 사항

Bandit 같은 정적 보안 테스팅 도구는 CLI 형태로 구현되어 있어 CI/CD 파이프라인에 통합하여 자동화를 구현하기 수월합니다. 이러한 정적 보안 테스팅 도구의 자동화는 지속적인 보안 검사를 가능하게 하고, 개발 과정에서 취약점을 조기에 발견하여 수정할 수 있도록 해줍니다. 보안성 높은 애플리케이션을 안정적으로 제공하기 위해 데브섹옵스를 실현하는 방법의 하나입니다. 이처럼 정적 보안 테스팅 도구를 자동화할 때 고려해야 할 주요 사항은 다음과 같습니다.

 

1) 자동화 계획 수립

모든 업무에서 그렇듯 보안 테스팅 자동화 작업에도 체계적인 계획 수립이 선행되어야 합니다. 대상 코드나 프로젝트에 적합한 도구와 검사 규칙을 선정하고, 검사 시기와 빈도, 보고 체계 등에 대한 전략을 세우는 것이 중요합니다. 기존 보안 문제 대응 프로세스와 조직의 특성을 고려해 일관된 대응 정책과 규칙을 마련해야 합니다.

 

또한 도구와 검사 규칙의 꾸준한 업데이트 계획 역시 함께 수립되어야 할 것입니다. 이런 업데이트는 새로운 취약점 유형에 대응하거나 보안 테스팅의 효율성을 높이는 데 도움이 됩니다.

 

2) CI/CD 파이프라인 통합

정적 보안 테스팅 도구는 코드 빌드 과정과 긴밀히 연계되어야 합니다. 따라서 도구를 CI/CD 파이프라인에 통합하여 지속적으로 코드 분석을 수행하고, 빌드 및 배포 프로세스에도 보안 검사 단계를 포함시키는 것이 바람직합니다. 이렇게 함으로써 애플리케이션 보안 수준을 높일 수 있습니다. 여기에 이슈 트래커 도구를 연동하면 발견된 취약점을 체계적으로 관리하고 개선할 수 있어 보안 활동의 효율성과 지속성을 높일 수 있습니다.

 

3) 오탐 문제 관리 

실습에서 살펴봤듯 오탐으로 인해 생성되는 결과는 불필요한 노이즈를 발생시킵니다. 이로 인해 개발 생산성이 저하되고, 실제로 자동화를 구현할 때 걸림돌이 되는 사례가 많습니다. 오탐 문제를 최소화하기 위해서는 정적 분석 도구의 검사 규칙을 프로젝트 특성에 맞게 세밀하게 구성하고 튜닝하는 작업이 필요합니다. 또한 특정 코드 패턴과 라이브러리를 제외 목록에 추가하거나 위험 수준 기준을 조정하는 등 방법으로 오탐 발생을 줄일 수 있습니다.

 

4) 지속적인 개선

기술이 발전함에 따라 새로운 유형의 보안 취약점이 발견되고 있습니다. 이에 정적 보안 테스팅 도구 역시 꾸준히 개선하여 신규 취약점을 탐지할 수 있는 검사 규칙을 반영해야 합니다. 따라서 관련 업데이트와 개선 사항에 대한 모니터링이 필수적입니다. 아울러 내부에서도 정적 분석 도구 활용 방식의 개선을 위해 피드백을 수렴하고 반영하는 노력이 필요합니다. 프로세스와 정책에 대한 주기적인 검토를 통해 지속적인 개선을 이루어나가는 것이 중요합니다.

 

5) 시큐어코딩 및 보안 교육

정적 보안 테스팅 도구의 결과를 정확히 이해하고 효과적으로 활용할 수 있게 교육을 제공하는 것 역시 중요합니다. 각 도구가 제시하는 취약점 유형, 위험 수준, 발생 원인 등에 대한 구체적인 설명과 실습 기회를 제공하는 것을 고려해야 합니다. 그래야 개발자들이 자동화 과정에서 발생하는 보안 이슈를 보다 쉽게 파악하고 빠르게 해결할 수 있습니다. 결국 자동화 과정에서 발견된 문제를 해결하는 것은 개발자이기 때문이죠.

 

더불어 이러한 교육 프로그램을 마련한다면 개발 단계에서부터 보안을 고려하는 시큐어 코딩 마인드셋과 실천 역량을 기를 수 있습니다. 코드를 작성하는 단계부터 보안 취약점이 발생할 가능성 자체를 원천적으로 줄이는 방법입니다. 개발자 보안 인식 제고와 역량 강화는 정적 분석 도구 활용을 넘어 결국 해당 기업의 전반적인 애플리케이션 및 서비스 보안 수준 향상으로 이어질 것입니다.

 

 

마치며

지금까지 Bandit 실습 예제와 함께 정적 보안 테스팅에 대해 자세히 살펴보았습니다. 데브섹옵스 실현의 일환으로 정적 보안 테스팅 도구를 자동화하면 소스 코드에 잠재된 보안 취약점을 개발 프로세스 초기 단계에서 발견하고 해결할 수 있습니다. 애플리케이션의 보안성을 높이고 잠재적인 위험과 비용을 크게 줄일 수 있죠.

 

다만 여기에는 오탐과 미탐 문제 등 한계점이 존재합니다. 이러한 한계를 극복하려면 도구 적용 시점부터 오탐 문제를 해결하기 위한 노력을 꾸준히 기울여야 합니다. 또한 동적 보안 테스팅, 소프트웨어 구성 요소 분석 도구 등 다른 데브섹옵스 도구와 통합하여 활용해 정적 테스팅만으로는 발견하기 어려운 보안 문제들을 추가로 탐지할 수 있을 것입니다.

 

요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.

좋아요

댓글

공유

공유

댓글 0
작가
27
명 알림 받는 중

작가 홈

작가
27
명 알림 받는 중
글로벌 오픈소스 기업에서 사이버 보안팀 팀리드를 맡고 있는 20년 이상 경력의 정보보안전문가입니다. “화이트해커를 위한 웹 해킹의 기술” 도서 저자이며 "버그잡는해커" 유튜브 채널에 강좌를 업로드합니다. 어렵게 느껴지는 사이버 보안 분야를 많은 분들에게 쉽게 전달하고 공유하고자 노력하고 있습니다.

좋아요

댓글

스크랩

공유

공유

지금 회원가입하고,
요즘IT가 PICK한 뉴스레터를 받아보세요!

회원가입하기
요즘IT의 멤버가 되어주세요! 요즘IT의 멤버가 되어주세요!
요즘IT의 멤버가 되어주세요!
모든 콘텐츠를 편하게 보고 스크랩해요.
모든 콘텐츠를 편하게 보고 스크랩 하기
매주 PICK한 콘텐츠를 뉴스레터로 받아요.
매주 PICK한 콘텐츠를 뉴스레터로 받기
로그인하고 무료로 사용하기