https://github.blog/security/vulnerability-research/attacking-browser-extensions/
background script and permissions
> 복사, 붙여넣기 같은 일반적인 사용자 동작과 겹치는 단축키를 생성해 사용자가 접근할 수 없어야 하는 탭과 상호작용 가능content scripts
사용자 방문 페이지와의 상호작용에서 프론트엔드도 중요한데, background script는 DOM에 접근할 수 없어 수행할 수 없다. → content scripts가 역할 수행
Attack Surface
1. a website loaded by the user
2. other installed extensions
contents script : 현재 웹사이트에서 데이터를 파싱하고, 그 데이터를 HTML 형태로 문서에 주입
→ 일부 확장 프로그램은 DOM 텍스트를 추출한 뒤 텍스트를 보기 좋게 꾸미거나 활용하려고 수정한 후 그 DOM 텍스트를 웹페이지에 반환한다. 이때, 텍스트가 HTML로 다시 삽입될 수 있도록 허용된다면, 해당 웹사이트에서 XSS 취약점이 발생할 수 있다.
sendMessage API : API를 통해 메세지를 전송하고, onConenctExternal/onMessageExternal API를 통해 메세지를 수신하면서 다른 확장 프로그램과 상호작용. 만약 확장 프로그램이 메세지의 발신자를 확인하지 않는다면, 이 기능에 임의로 접근 가능.
manifest 설정 방식에도 관심을 가져야 하는데
external_connectable 를 보면 연결이 가능한 website나 extension ID를 확인할 수 있다. 여기서 설정이 잘못되면, onMessageExternal, onConnectExternal이 다른 확장 프로그램 대상을 넘어서 웹사이트에도 접근이 가능해지면서 위험도가 올라간다.
web_accessible_resources
1. HTML 파일 - web accessible → 해당 HTML 파일을 iframe로 불러올 수 있다. 이때, 페이지가 URL 매개변수를 받아 이를 권한 있는 방식으로 사용하면, 악성 웹사이트가 권한 있는 동작을 수행토록 악용할 수 있다.
2. HTML 페이지 - sensitive actions & web accessible → clickjacking
clickjacking_관련 게시글
이런 부분들이 동시에 일어나야 해서 취약점이 잘 탐지되지 않았었다, 이제까지는.
XSS - content scripts & background script context
CSP를 확인해봐야 되는데, manifest v2, v3에서는 unsafe-inline 지시어가 허용되지 않아서 팝업이나 옵션 페이지가 있는 확장 프로그램에 포함된 html 페이지는 xss가 일어나지 않는다. HTML 인젝션 공격은 또 모르지만.
manfiest v2에서는 unsafe-eval 속성이 허용되었고, v3에서는 폐기됐다. 그래서 xss 취약점을 찾을 때 unsafe-eval이 있는지 확인해봐야 한다.
함수 → eval(), function(), setTimeout(), setInterval(), extension API의 executeScript
구버전 firefox 확장 프로그램은 manifest v2 확장 프로그램을 신규로 받고 있어서 취약할 가능성이 더 크다.
https://palant.info/2022/08/24/attack-surface-of-extension-pages/ : 구버전 jQuery, unsafe-eval 사용 시 발생할 수 있는 취약점 + 공격 시연 코드
SSRF
서버사이드 요청 위조(SSRF)는 웹 애플리케이션에서 흔히 발견되는 취약점이며, 브라우저 확장 프로그램에서도 나타날 수 있습니다. 확장 프로그램은 웹 애플리케이션과 유사하지만 클라이언트 브라우저의 쿠키와 함께 실행됩니다. 공격자가 XMLHTTPRequest나 fetch 같은 네트워크 요청의 URL을 제어할 수 있다면 SSRF가 발생할 수 있습니다. SSRF의 효과는 사용된 요청 방식, 확장 프로그램 개발자가 요청에 인증 정보/쿠키를 포함했는지 여부, 그리고 확장 프로그램 manifest의 permissions/host_permissions 항목에 해당 웹사이트가 포함되어 있는지 여부에 따라 달라집니다.
v2에서 v3로의 전환 과정에서 확장 프로그램의 요청 능력에도 변화가 있었습니다. 구체적으로 manifest v2와 Firefox에서는, 권한이 없는 확장 프로그램도 쿠키를 포함해 임의의 도메인에 요청을 보낼 수 있었지만, SameSite 쿠키는 올바른 권한을 가진 경우에만 전송할 수 있었습니다. 반면 Chromium에서는 권한이 없는 확장 프로그램이 쿠키와 함께 요청을 보낼 수 없었습니다. v3 확장 프로그램의 경우, 어떤 쿠키도 요청에 포함시키려면 반드시 host_permissions를 선언해야 합니다. 이는 Firefox의 v2 환경이 v3보다 SSRF 공격에 훨씬 더 강력할 수 있음을 의미하며, Firefox AddOn Store가 신규 확장 프로그램에 v3를 강제하지 않는 점과 맞물려, Firefox 확장 프로그램이 Chromium보다 SSRF 공격에 더 취약한 상황을 만듭니다.
Extension API Injection
Extension API 인젝션은 브라우저 확장 프로그램에서만 발생하는 독특한 취약점입니다. 공격자가 제어하는 데이터가 API 호출에 주입될 수 있다면, 공격자는 해당 확장 프로그램의 권한을 획득할 수 있습니다. 일반적으로 API는 데이터를 변경하는 것과 유출하는 것으로 나눌 수 있습니다. 데이터를 변경하는 API 예시로는 downloads.download(), 북마크 생성/삭제 함수, 그리고 쿠키 설정 함수 등이 있습니다. 당연히 이러한 API들은 안전한 기본값을 갖추고 있습니다. 예를 들어 다운로드 메서드는 사용자 정의 Downloads 폴더로만 저장할 수 있고, 경로 조작(path traversal) 공격 등은 차단됩니다.
또 다른 예시는 tabs.update()입니다. 브라우저 주소창에 javascript:alert(document.domain)을 입력하면 현재 접근 중인 웹사이트의 도메인을 보여주는 알림이 뜨는데, 과거에는 tabs.update()를 이용해 이를 프로그래밍적으로 실행하여 XSS를 발생시킬 수 있었습니다. 그러나 이 취약점은 이미 패치되었습니다. 대부분의 API 인젝션 공격은 DOS 공격이나 정보 유출로 이어지는데, 예를 들어 공격자가 무한히 많은 파일을 다운로드하게 만들어 디스크를 가득 채우거나, 북마크를 생성/삭제하여 사용자를 괴롭히는 식입니다. 다만 이는 전통적인 웹 애플리케이션 공격 프리미티브보다는 덜 강력합니다.
방어 수단
개발자들이 확장 프로그램 ID를 랜덤화해서, 내부 ID(UUID)가 유출되지 않는 이상 노출된 html 파일을 공격하지 못하도록 만들었다.UUID를 기준으로 상대 경로를 갖는데, 페이지 자체에서 더 이상 접근이 불가하다. chromium은 아직 괜찮다는데 이 부분은 확인 필요. firefox는 컨테이너 단위로, safari는 application 재시작 시 UUID를 랜덤화한다.
CodeQL을 활용한 모델링
웹 애플리케이션 취약점과 마찬가지로, 브라우저 확장 프로그램의 취약점 역시 CodeQL로 모델링할 수 있습니다. CodeQL은 이미 XSS, SSRF와 같은 많은 취약점을 지원하고 있으며, 이를 우리의 쿼리 기반으로 사용할 수 있습니다. CodeQL의 코드 인젝션 쿼리는 RemoteFlowSource(외부 시스템이나 사용자로부터 데이터를 받을 수 있는 모든 JavaScript API)를 가져와, eval 같은 JavaScript 코드 인젝션 sink로의 흐름을 추적합니다. 이러한 sink들은 브라우저 확장 프로그램에서도 중요하지만, 브라우저에만 적용되는 추가적인 sink도 존재합니다. 따라서 브라우저 확장 프로그램에 적용할 수 있는 sink 모듈을 정의하고, Code Injection 쿼리의 Sink 클래스를 확장하여 CodeQL이 이 sink들을 고려하도록 만들 수 있습니다.
추가로 읽을 내용