알렉스 나달린 저
웹 애플리케이션 보안 소개
_사진 제공:[Unsplash](https://unsplash.com/photos/cVMaxt672ss?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText" rel="noopener" target="_blank" title="">Liam Tucker,
Chrome, Firefox, Edge, Safari 등 가장 널리 사용되는 브라우저 중 하나를 사용하는 데 익숙할 수도 있지만 그렇다고 해서 다른 브라우저가 없다는 의미는 아닙니다.
예를 들어, lynx는 명령줄에서 작동하는 경량의 텍스트 기반 브라우저입니다. Lynx의 핵심에는 다른 "주류" 브라우저에서 볼 수 있는 것과 똑같은 원칙이 있습니다. 사용자가 웹 주소(URL)를 입력하면 브라우저가 문서를 가져와서 렌더링합니다. 유일한 차이점은 lynx가 시각적 렌더링 엔진을 사용하지 않고 Google과 같은 웹사이트를 다음과 같이 만드는 텍스트 기반 인터페이스를 사용한다는 점입니다.

우리는 브라우저가 수행하는 작업을 광범위하게 이해하고 있지만 이러한 독창적인 애플리케이션이 수행하는 단계를 자세히 살펴보겠습니다.
브라우저는 어떤 역할을 하나요?
간단히 말해서, 브라우저의 작업은 주로 다음으로 구성됩니다:
- DNS 해상도
- HTTP 교환
- 렌더링
- 헹구고 반복
DNS 해상도
이 프로세스를 통해 사용자가 URL을 입력하면 브라우저는 어떤 서버에 연결해야 하는지 알 수 있습니다. 브라우저는 google.com을 찾기 위해 DNS 서버에 접속합니다. 216.58.207.110로 번역됩니다. , 브라우저가 연결할 수 있는 IP 주소입니다.
HTTP 교환
브라우저가 요청을 처리할 서버를 식별하면 해당 서버와 TCP 연결을 시작하고 HTTP 교환을 시작합니다. . 이는 브라우저가 필요한 것을 서버와 통신하고 서버가 응답하는 방법일 뿐입니다.
HTTP는 단순히 웹에서 통신하는 데 가장 널리 사용되는 프로토콜의 이름이며, 브라우저는 서버와 통신할 때 대부분 HTTP를 통해 통신합니다. HTTP 교환에는 클라이언트(브라우저)가 요청을 보내는 것과 관련됩니다. , 서버는 응답으로 응답합니다. .
예를 들어, 브라우저가 google.com 뒤의 서버에 성공적으로 연결된 후 , 다음과 같은 요청을 보냅니다:
GET / HTTP/1.1Host: google.comAccept: */*
요청을 한 줄씩 분석해 보겠습니다.
GET / HTTP/1.1:이 첫 번째 줄을 사용하면 브라우저는/위치에 있는 문서를 검색하도록 서버에 요청합니다. , 요청의 나머지 부분은 HTTP/1.1 프로토콜을 따를 것이라고 덧붙였습니다(1.0를 사용할 수도 있음). 또는2)Host: google.com:HTTP/1.1에서 필수인 유일한 HTTP 헤더입니다. . 서버는 여러 도메인(google.com)을 제공할 수 있으므로 ,google.co.uk등) 여기서 클라이언트는 해당 요청이 해당 특정 호스트에 대한 것이라고 언급합니다.Accept: */*:브라우저가 서버에 모든 종류의 응답을 수락할 것임을 알리는 선택적 헤더입니다. 서버에는 JSON, XML 또는 HTML 형식으로 사용 가능한 리소스가 있을 수 있으므로 선호하는 형식을 선택할 수 있습니다.
클라이언트 역할을 하는 브라우저 다음 , 요청이 완료되면 서버가 응답할 차례입니다. 응답은 다음과 같습니다:
HTTP/1.1 200 OKCache-Control: private, max-age=0Content-Type: text/html; charset=ISO-8859-1Server: gwsX-XSS-Protection: 1; mode=blockX-Frame-Options: SAMEORIGINSet-Cookie: NID=1234; expires=Fri, 18-Jan-2019 18:25:04 GMT; path=/; domain=.google.com; HttpOnly
<!doctype html><html">......</html>
와, 소화해야 할 정보가 너무 많네요. 서버는 요청이 성공했음을 알려줍니다(200 OK ) 응답에 몇 가지 헤더를 추가합니다. , 예를 들어 요청을 처리한 서버를 광고합니다(Server: gws ), X-XSS-Protection이 뭐죠? 이 대응 정책 등등.
지금 당장은 응답의 모든 줄을 모두 이해할 필요는 없습니다. 이 시리즈의 후반부에서 HTTP 프로토콜, 헤더 등을 다룰 예정입니다.
지금으로서 이해해야 할 것은 클라이언트와 서버가 정보를 교환하고 있으며 그 교환이 HTTP를 통해 이루어진다는 것입니다.
렌더링
마지막으로 렌더링 프로세스. 사용자에게 표시되는 것이 재미있는 문자 목록뿐이라면 브라우저는 얼마나 좋을까요?
<!doctype html><html">......</html>
본문 응답의 경우 서버는 Content-Type에 따른 응답 표현을 포함합니다. 헤더. 우리의 경우 콘텐츠 유형은 text/html로 설정되었습니다. 이므로 응답에 HTML 마크업이 있을 것으로 예상됩니다. 이것이 바로 본문에서 찾은 내용입니다.
이것이 브라우저가 진정으로 빛나는 곳입니다. 이는 HTML을 구문 분석하고 마크업에 포함된 추가 리소스(예:가져올 JavaScript 파일이나 CSS 문서가 있을 수 있음)를 로드한 후 이를 사용자에게 최대한 빨리 제공합니다.
다시 한 번 말하지만, 최종 결과는 일반 Joe가 이해할 수 있는 것입니다.

브라우저의 주소 표시줄에 Enter 키를 눌렀을 때 실제로 어떤 일이 발생하는지에 대한 더 자세한 내용을 보려면 프로세스 이면의 메커니즘을 설명하는 매우 정교한 시도인 "..."을 읽어 보시기 바랍니다.
이 시리즈는 보안에 초점을 맞춘 시리즈이므로 방금 배운 내용에 대한 힌트를 드리려고 합니다. 공격자는 HTTP 교환 및 렌더링 부분의 취약점을 이용해 쉽게 생존할 수 있습니다. . 취약점과 악의적인 사용자는 다른 곳에도 숨어 있지만 이러한 수준에서 더 나은 보안 접근 방식을 사용하면 이미 보안 상태를 개선하는 데 큰 진전을 이룰 수 있습니다.
공급업체
가장 인기 있는 브라우저 4개는 서로 다른 공급업체에 속합니다:
- Google 크롬
- Mozilla의 Firefox
- Apple의 사파리
- Microsoft의 Edge
공급업체는 시장 침투력을 높이기 위해 서로 싸우는 것 외에도 웹 표준을 개선하기 위해 서로 협력합니다. , 이는 브라우저에 대한 일종의 '최소 요구 사항'입니다.
W3C는 표준 개발의 주체이지만 브라우저가 최종적으로 웹 표준이 되는 자체 기능을 개발하는 것은 드문 일이 아니며 보안도 이에 예외는 아닙니다.
예를 들어 Chrome 51에서는 웹 애플리케이션이 CSRF(나중에 자세히 설명)라고 알려진 특정 유형의 취약점을 제거할 수 있게 해주는 기능인 SameSite 쿠키를 도입했습니다. 다른 벤더들도 이것이 좋은 생각이라고 판단하고 이를 따라 SameSite를 웹 표준으로 만들었습니다. 현재로서는 Safari가 SameSite 쿠키를 지원하지 않는 유일한 주요 브라우저입니다.

이는 우리에게 두 가지 사실을 알려줍니다:
- Safari는 사용자 보안에 충분히 신경을 쓰지 않는 것 같습니다. (농담입니다. SameSite 쿠키는 Safari 12에서 사용할 수 있으며 이 기사를 읽고 있는 시점에는 이미 출시되었을 수도 있습니다.)
- 한 브라우저의 취약점을 패치한다고 해서 모든 사용자가 안전하다는 의미는 아닙니다.
첫 번째 포인트는 Safari에서 촬영하는 것입니다(앞서 언급했듯이 농담입니다!). 두 번째 포인트는 정말 중요합니다. 웹 애플리케이션을 개발할 때 다양한 브라우저에서 동일하게 보이는지 확인해야 할 뿐만 아니라 플랫폼 전반에서 사용자가 동일한 방식으로 보호되는지 확인해야 합니다.
웹 보안에 대한 전략은 브라우저 공급업체가 허용하는 작업에 따라 달라져야 합니다. . 요즘 대부분의 브라우저는 동일한 기능 세트를 지원하고 공통 로드맵에서 거의 벗어나지 않지만 위와 같은 사례는 여전히 발생하며 이는 보안 전략을 정의할 때 고려해야 할 사항입니다.
우리의 경우 SameSite 쿠키를 통해서만 CSRF 공격을 완화하기로 결정했다면 Safari 사용자를 위험에 빠뜨리고 있다는 점을 인식해야 합니다. 그리고 우리 사용자들도 그 사실을 알아야 합니다.
마지막으로, 브라우저 버전을 지원할지 여부를 결정할 수 있다는 점을 기억해야 합니다. 각각의 모든 브라우저 버전을 지원하는 것은 비실용적입니다(Internet Explorer 6을 생각해 보세요). 하지만 주요 브라우저의 마지막 몇 가지 버전이 지원되는지 확인하는 것은 일반적으로 좋은 결정입니다. 하지만 특정 플랫폼에 보호 기능을 제공할 계획이 없다면 일반적으로 사용자에게 알리는 것이 좋습니다.
프로 팁 :사용자에게 오래된 브라우저를 사용하도록 권장하거나 적극적으로 지원해서는 안 됩니다. 필요한 모든 예방 조치를 취했더라도 다른 웹 개발자는 그렇지 않았을 수도 있습니다. 사용자에게 주요 브라우저 중 하나의 최신 지원 버전을 사용하도록 권장하십시오.
공급업체 또는 표준 버그
일반 사용자가 제3자 클라이언트(브라우저)를 통해 우리 애플리케이션에 액세스한다는 사실은 명확하고 안전한 브라우징 경험을 향한 또 다른 수준의 간접적인 요소를 추가합니다. 즉, 브라우저 자체가 보안 취약성을 나타낼 수 있습니다.
공급업체는 일반적으로 보상(버그 포상금이라고도 함)을 제공합니다. ) 브라우저 자체의 취약점을 발견할 수 있는 보안 연구원에게 제공됩니다. 이러한 버그는 구현과 관련이 있는 것이 아니라 브라우저가 자체적으로 보안을 처리하는 방식과 관련이 있습니다.
예를 들어 Chrome 보상 프로그램을 통해 보안 엔지니어는 Chrome 보안팀에 연락하여 발견한 취약점을 보고할 수 있습니다. 이러한 취약점이 확인되면 패치가 발행되고 일반적으로 보안 권고 공지가 대중에게 공개되며 연구원은 프로그램으로부터 (대개 금전적인) 보상을 받습니다.
Google과 같은 회사는 버그 바운티 프로그램에 상대적으로 많은 자본을 투자합니다. 애플리케이션에서 문제가 발견될 경우 금전적 혜택을 약속하여 연구원을 유치할 수 있기 때문입니다.
버그 바운티 프로그램에서는 모두가 승리합니다. 공급업체는 소프트웨어의 보안을 개선하고 연구원은 발견한 대가를 받습니다. 버그 바운티 이니셔티브는 보안 환경에서 자체적인 영역을 차지할 가치가 있다고 믿기 때문에 이러한 프로그램에 대해서는 나중에 논의할 것입니다.
Jake Archibald는 최근 두 개 이상의 브라우저에 영향을 미치는 취약점을 발견한 Google의 개발자 옹호자입니다. 그는 자신의 노력, 다양한 공급업체에 접근한 방법, 그들의 반응을 흥미로운 블로그 게시물에 기록했습니다. 이 게시물을 읽어보시기 바랍니다.
개발자를 위한 브라우저
지금쯤이면 우리는 매우 간단하지만 중요한 개념, 즉 브라우저는 단순히 일반 인터넷 사용자를 위해 만들어진 HTTP 클라이언트일 뿐입니다를 이해했을 것입니다. .
플랫폼의 기본 HTTP 클라이언트보다 확실히 더 강력합니다(NodeJS의 require('http')를 생각해 보세요). , 예를 들어) 그러나 결국에는 더 단순한 HTTP 클라이언트의 "그냥" 자연스러운 진화일 뿐입니다.
개발자로서 우리가 선택한 HTTP 클라이언트는 아마도 웹 개발자가 매일 사용하는 가장 인기 있는 소프트웨어 프로그램 중 하나인 Daniel Stenberg의 cURL일 것입니다. 이를 통해 명령줄에서 HTTP 요청을 보내 즉석에서 HTTP 교환을 수행할 수 있습니다.
$ curl -I localhost:8080
HTTP/1.1 200 OKserver: ecstatic-2.2.1Content-Type: text/htmletag: "23724049-4096-"2018-07-20T11:20:35.526Z""last-modified: Fri, 20 Jul 2018 11:20:35 GMTcache-control: max-age=3600Date: Fri, 20 Jul 2018 11:21:02 GMTConnection: keep-alive
위 예에서는 localhost:8080/에 문서를 요청했습니다. , 로컬 서버가 성공적으로 응답했습니다.
응답 본문을 명령줄에 덤프하는 대신 여기서는 -I을 사용했습니다. cURL에게 응답 헤더에만 관심이 있음을 알려주는 플래그입니다. 한 단계 더 나아가, cURL이 수행하는 실제 요청을 포함하여 조금 더 많은 정보를 덤프하도록 지시하여 전체 HTTP 교환을 더 잘 볼 수 있습니다. 사용해야 하는 옵션은 -v입니다. (상세하게):
$ curl -I -v localhost:8080* Rebuilt URL to: localhost:8080/* Trying 127.0.0.1...* Connected to localhost (127.0.0.1) port 8080 (#0)> HEAD / HTTP/1.1> Host: localhost:8080> User-Agent: curl/7.47.0> Accept: */*>< HTTP/1.1 200 OKHTTP/1.1 200 OK< server: ecstatic-2.2.1server: ecstatic-2.2.1< Content-Type: text/htmlContent-Type: text/html< etag: "23724049-4096-"2018-07-20T11:20:35.526Z""etag: "23724049-4096-"2018-07-20T11:20:35.526Z""< last-modified: Fri, 20 Jul 2018 11:20:35 GMTlast-modified: Fri, 20 Jul 2018 11:20:35 GMT< cache-control: max-age=3600cache-control: max-age=3600< Date: Fri, 20 Jul 2018 11:25:55 GMTDate: Fri, 20 Jul 2018 11:25:55 GMT< Connection: keep-aliveConnection: keep-alive
<* Connection #0 to host localhost left intact
DevTools를 통해 주류 브라우저에서도 거의 동일한 정보를 사용할 수 있습니다.
우리가 본 것처럼 브라우저는 정교한 HTTP 클라이언트에 지나지 않습니다. 물론 그들은 엄청난 양의 기능(자격 증명 관리, 북마크, 기록 등)을 추가하지만 사실은 인간을 위한 HTTP 클라이언트로 태어났습니다. 대부분의 경우 웹 애플리케이션의 보안을 테스트하기 위해 브라우저가 필요하지 않으며 간단히 "말아서" 응답을 볼 수 있으므로 이는 중요합니다.
마지막으로 지적하고 싶은 점은 무엇이든 브라우저가 될 수 있다는 것입니다. . HTTP 프로토콜을 통해 API를 사용하는 모바일 애플리케이션이 있다면 그 앱은 바로 브라우저입니다. 이 앱은 여러분이 직접 만든 고도로 맞춤화된 애플리케이션일 뿐이며 (자신의 API에서 오는) 특정 유형의 HTTP 응답만 이해하는 것입니다.
HTTP 프로토콜 속으로
앞서 언급했듯이 HTTP 교환 및 렌더링 단계는 가장 많은 수의 공격 벡터를 제공하므로 우리가 주로 다룰 단계입니다. 악의적인 사용자를 위한 것입니다.
다음 글에서는 HTTP 프로토콜에 대해 더 자세히 살펴보고 HTTP 교환을 보호하기 위해 어떤 조치를 취해야 하는지 알아보겠습니다.
원래 odino.org에 게시됨(2018년 7월 29일)
_트위터에서 저를 팔로우하실 수 있습니다. 호언장담을 환영합니다!_ ?
무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요