Contrast Security 사의 연구에 따르면 애플리케이션 중 90% 이상이 개발 및 QA 단계에서 취약점 검사를 받지 않는 것으로 드러났습니다. 사실, 우리는 수많은 보안 문제를 간과하거나 놓치게 됩니다. 이는 애플리케이션 개발 프레임워크를 보호하는 것이 중요함을 뜻합니다. StackOverflow의 한 조사에서는 소프트웨어 엔지니어 중 약 31%가 AngularJS를 이용하여 사용자 인터페이스를 만드는 것으로 파악되었습니다. 그만큼 AngularJS의 보안 기능이 매우 중요하다고 할 수 있습니다.
AngularJS의 보안
AngularJS은 오픈소스 프런트엔드 자바스크립트 프레임워크입니다. 클라이언트 측에 편리한 데이터 바인딩 옵션을 제공하며 개발자에게는 HTML 템플릿에서 탈피하여 보다 원활한 개발이 이루어지도록 도와줍니다. 또한 자동 출력 인코딩과 같은 보안 기능을 제공하면서 Strict Contextual Escaping을 지원하고 내장 콘텐츠 보안 정책(CSP)을 갖추었지만 문제와 단점도 존재합니다.
AngularJS의 보안은 애플리케이션 전반적 보안에 있어 기반 역할을 하므로 이를 우선적으로 보강해야 할 것입니다. 놀랍게도 한 조사에서는 관리자들은 55%가 보안 코딩 업무 표준을 이용한 반면에 개발자들 중 단 43%만이 보안 코딩 업무 방식과 표준을 이용하는 것으로 나타났습니다. 또한 79%는 ‘보안 코드’의 중요성이 높아진다는 데 동의했습니다. 이는 애플리케이션 보안의 좋은 사례 미 표준에 대한 이해와 그 실천이 필요함을 의미하며 AngularJS 관점에서 더욱 중요하다고 할 수 있습니다.
AngularJS는 구체적으로 인라인 스타일을 사용하지만 공격자는 맞춤형 인젝션 콘텐츠로 이를 쉽게 우회할 수 있습니다. 특히 취약한 측면은 크로스 사이트 스크립팅(XSS), 프로토타입 오염, 서비스 거부(DoS), 클릭재킹, 임의 코드 실행, 임의 명령어 실행, 위험 오브젝트 역직렬화, 보호 우회 및 임의 스크립트 인젝션 등이 있습니다.
공격자는 아래와 같이 템플릿을 제어할 수 있습니다.
- 사용자 제공 콘텐츠가 있는 서버 측에서 템플릿 생성
- 특정 메소드에 대한 호출이나 표현식을 구문 분석하는 서비스에 대한 호출 또는 orderBy 파이프에 대한 술어로 사용자 제공 콘텐츠에서 생성된 표현식을 전달하는 방식
로컬 애플리케이션에 영향을 미치지 않고 잠재적으로 안전하지 않은 소프트웨어 코드를 실행하기 위한 용도로 만들어진 가상머신인 샌드박스는 여기에 도움이 되지 않습니다. 샌드박스는 AngularJS 표현식이 안전하지 않은 표현식을 평가하지 못하도록 제한하지 않으므로 함수 생성자, 윈도우 오브젝트, DOM 엘리먼트, 글로벌 변수, 객체 생성자에 대한 접근을 제한하지 않습니다. 즉 공격자는 이미 실행된 기능만 실행할 수 있고 수학적 함수를 실행하거나 범위 변수에서 데이터를 표시 또는 수정할 수 있습니다. 이는 확실히 공격의 영향을 제한할 수 있습니다. 다만 공격자가 샌드박스를 빠져나와 악성 자바스크립트를 HTML 페이지 내에서 실행할 수 있으므로 이 방법만으로는 충분하지 못합니다. 즉 샌드박스는 AngularJS 보안 관점에서 부족합니다.
AngularJS 애플리케이션 보안을 위한 팁
개발자는 아래와 같은 기본 원칙에 따라 보다 강력한 AngularJS 보안을 구현해야 합니다.
기초를 확실히 합니다.
공격자가 클라이언트 측 템플릿을 수정하지 못하도록 애플리케이션을 설계하십시오. XSS 취약점을 방지하기 위해 클라이언트와 서버 템플릿을 혼합하지 않고, 동적 템플릿 생성을 위해 사용자 입력을 이용하지 않으며, 긴밀하게 통합된 CSP를 사용하는 것이 좋은 사례입니다.
최신 버전을 사용하고 커스터마이징을 피합니다.
AngularJS의 최신 버전과 라이브러리를 이용하는 것이 최신 보안 중심 기능을 적절히 이용하는 좋은 출발점입니다. Angular Change 로그로 보안 관련 업데이트와 패치를 확인하십시오. 또한 필요에 따라 라이브러리를 커스터마이징하는 행동은 다음과 같은 두 가지 문제가 있으므로 피하는 것이 최선입니다. 하나는 AngularJS의 최신 버전으로 업그레이드할 때 발생하는 문제이고, 다른 하나는 중요한 보안 패치를 누락하는 문제입니다.
기본 AngularJS 보안 기능을 활용합니다.
AngularJS가 기본으로 제공하는 자동 출력 인코딩과 컨텍스트 인식 입력 삭제 기능도 좋은 옵션입니다. 이는 모든 안전하지 않은 기호와 HTML 제어 문자에 인코딩되는 XSS 취약점 완화에 도움이 되며, 주로 ng-bind와 함께 사용됩니다.
DOM API의 사용을 제한합니다.
Angular DOM 관련 입력 인젝션이나 DOM API의 직접 사용을 피하고 그 대신 DOM과 상호작용할 시 Angular 템플릿과 데이터 바인딩을 이용해야 합니다. ‘Trusted Types’을 강제하지 않는다면 서드파티 API나 라이브러리를 이용할 시 위험한 메소드가 발생할 수 있습니다. 신뢰할 수 없는 값은 DomSanitizer.sanitize 기능으로 삭제해야 합니다. 꽤 많은 Angular API가 보안 위험을 내포하고 있으며, 특히 DOM에 대한 직접 접근을 제공하는 ElementRef가 이에 해당합니다. 이를 피하고자 다른 템플릿이나 데이터 바인딩 등과 같은 네이티브 옵션을 대신 사용할 수 있습니다.
템플릿 인젝션 및 내부 템플릿만 이용합니다.
오프라인 템플릿 컴파일러인 템플릿 인젝션 기능으로 성능을 높이고 보안 기능을 이용할 수 있습니다. 특히 이는 생산 및 구현 단계에서 이용해야 합니다. 그 외에도 템플릿을 오프라인으로 컴파일하는 데 도움이 되는 Angular의 Ahead of Time 컴파일러를 이용하는 방법도 좋습니다. 개발자들은 여러 출처의 템플릿을 불러오는 습관이 있으며 이는 이해할 만합니다. 다만 신뢰할 수 없는 도메인은 취약점을 더욱 강하게 만들 수 있습니다. 서드파티 오픈소스 패키지를 이용할 시에는 정기적으로 검사하고 수정사항도 포함해야 합니다.
위험한 패턴은 피하고 템플릿은 하나의 애플리케이션 컨텍스트에서만 처리합니다.
window.location.href = $location.hash와 같은 패턴은 해커들을 불러모으는 것이나 다름없습니다. 오픈 리디렉션과 자바스크립트 코드 인젝션을 피하고 페이지 참조와 내비게이션에 딕셔너리 맵을 사용하십시오. 템플릿은 클라이언트나 서버 측에서 하나의 애플리케이션 컨텍스트에서만 처리하여 서버측 코드 인젝션을 줄여야 합니다. Angular의 angular.element() jQuery 호환 DOM API 조작은 피하십시오. 이는 DOM에서 직접 HTML 요소를 생성하여 더 많은 XSS 취약점이 발생하게 됩니다.
보안 린터를 사용합니다.
개발자는 보안 린터를 사용하여 기본적인 정적 보안 분석을 실시하고 오류, 버그, 보안 취약점에 대한 레드 플래그를 제공할 수 있습니다. AngularJS의 경우 일반 코드 방식, 규칙, 보안 지침에 도움이 되는 ‘eslint-plugin-scanjs-rules’ 및 ‘eslint-plugin-angular’가 해당 됩니다.
내장 보안 기능을 살펴봅니다.
AngularJS의 내장 크로스 사이트 요청 위조(CSRF) 토큰과 크로스 사이트 스크립트 포함(XSSI) 기능으로 HTTP 수준의 취약점을 줄이십시오. CSRF는 공격자가 다른 페이지로 사용자를 리디렉션하고 악성 요청을 서버로 전송하게 만들 수 있습니다. 또한 개발자는 자동 생성된 인증 토큰을 이용하고 사용자의 브라우저가 전송한 원본 헤더를 확인하며 인증 토큰은 자신의 애플리케이션에만 보이도록 할 수 있습니다. CSRF의 경우 클라이언트와 서버 양측의 토큰 값을 비교하여 매치 포스트가 존재하는지 확인하고 요청을 처리할 수 있습니다. 다만 개발자는 이 기능을 자신의 서버 측에서 구현해야 합니다.
DomSantizer를 적절히 사용합니다.
XSS 공격은 해커들이 특정 패키지의 DOM 요소에 스크립트를 삽입하는 가장 일반적인 데이터 탈취 공격입니다. 그 다음으로 악성소프트웨어 공격까지 일어날 수 있습니다. 그러므로 HTML, CSS, 자원 URL, 스타일, URL, 속성에 걸쳐 신뢰하지 않는 입력에 대해 신뢰할 수 없는 값을 검사하여 안전한 값으로 바꾸는 ‘삭제’와 파일 참조가 권장됩니다. DomSanitizer가 여기서 좋은 방법입니다. 이는 아래의 3가지 중요한 기능을 제공합니다.
- sanitizeHTML 기능 – HTML 값을 먼저 파싱한 다음 그 토큰을 검증하여 확인합니다.
- sanitizeStlye 기능 – 정규식을 이용하여 신뢰할 수 없는 스타일과 URL 값을 삭제합니다.
- sanitizeURL 기능 – 정규 표현식을 사용하여 신뢰할 수 없는 URL 값을 수정합니다.
AngularJS 보안의 미래
엄청난 속도로 대량의 애플리케이션들이 개발되는 가운데 유입 트래픽을 확인하기 위해 인간이 직접 개입하는 것은 장기적 해법이 될 수 없습니다. 그러므로 런타임 애플리케이션 자가 보호(RASP)가 필요합니다. 단순히 의심스러운 트래픽을 차단하고 그 주변만 살펴보는 범용 방화벽이나 웹 애플리케이션 방화벽과 달리 RASP는 적극적으로 유입되는 애플리케이션 호출을 차단하여 악성 소프트웨어나 위협이 존재하는지 확인합니다. RASP는 애플리케이션과 통합되므로 알려진 취약점을 중화시킬 뿐 아니라 알려지지 않은 공격으로부터 애플리케이션을 보호할 수 있습니다.
또한 실시간으로 작동하고 사용자의 개입이 필요하지 않으며 코드베이스, API, 시스템 구성 등에서 필요한 정보를 취해 컨텍스트화된 서비스를 제공하는 동시에 애플리케이션 내에 상주하므로 오탐을 줄이고 매우 근접한 곳에서 애플리케이션을 감시하여 의심스러운 행동을 추적합니다.
웹과 웹 외의 애플리케이션을 모두 보호하며 공격자가 방호를 침투한 후에도 시스템을 보호할 수 있습니다. 애플리케이션 로직, 구성, 데이터 이벤트 흐름의 통찰력을 통해 위협 감지와 방지의 정확성을 높입니다.
AngularJS의 보안을 강화하는 AppSealing
앞서 언급한 조사에서 97%는 충분한 교육을 받는다고 생각하지만 91%나 되는 응답자들은 실제로 보안 코딩 방식을 실천할 시에 아직 더 큰 어려움을 겪는다고 인정했습니다. 또한 88%는 보안 코딩이 매우 어렵다고 답했습니다. 애플리케이션 보안은 확실히 시간 문제이지만 길이 명확해 보이지는 않습니다. 하지만 AppSealing이 도와드릴 수 있습니다.
AppSealing의 풍부한 앱 보호 경험과 전문성을 통해 단 한 줄의 코드도 작성하지 않고 애플리케이션을 보호하십시오. AppSealing의 안정적인 보안 프레임워크와 동적인 사용량 기반 과금제는 iOS와 Android 애플리케이션에 대해 완전하면서 전체적인 보안을 제공합니다.