나는 지금까지 프로젝트를 해오면서 helmet이 그냥 Xss공격에 대한 방어를 해준다고 일반적으로 쓰듯이
app.use(helmet())
으로만 써왔는데 이번 프로젝트에 API의 보안에 집중하면서 이 라이브러리에 좀 더 집중하게 되었다.
일단 간단히 helmet 라이브러리를 소개하면
helmet은 Express 애플리케이션의 보안을 강화하는 데 도움이 되는 다양한 HTTP 헤더를 설정하는 미들웨어 기능 모음이다
라이브러리 패키지 다운은 다른 라이브러리와 똑같이 npm이나 yarn을 통해 다운받아서 사용하면 된다
npm i helmet
const express = require('express') const helmet = requirre('helmet') const app = express() app.use(helmet())
위와 같이 app.use(helmet())만 설정 할 때는 helmet에서 기본으로 제공하는 보안기능만 적용해 준다.
이 헤더는 페이지에 리소스를 로드하기 위한 정책을 설정합니다. 기본 정책은 'self'로 설정되어 있으며, 이는 페이지와 동일한 출처에서만 리소스를 로드할 수 있음을 의미합니다. 이 정책에는 font-src의 경우 'https' 및 img-src의 경우 'data'와 같은 다양한 유형의 리소스에 대한 기타 특정 소스도 포함됩니다.
페이지에 포함될 때 다른 출처에서 리소스를 로드하기 위한 정책을 설정합니다. 기본값은 'require-corp'로 설정되어 있습니다. 즉, 리소스의 출처에 유효한 Cross-Origin-Resource-Policy 헤더가 있는 경우에만 리소스가 로드됩니다.
링크 또는 window.open으로 열 때 다른 출처에서 리소스를 로드하기 위한 정책을 설정합니다. 기본값은 'same-origin'으로 설정되어 있습니다. 이는 페이지와 동일한 출처의 창이나 링크로만 리소스를 열 수 있음을 의미합니다.
다른 출처에서 리소스를 로드하기 위한 정책을 설정합니다. 기본값은 'same-origin'으로 설정되어 있습니다. 즉, 리소스가 페이지와 동일한 출처에서 온 경우에만 로드할 수 있습니다.
Referer 헤더와 함께 전송되는 정보의 양을 제어합니다. 기본값은 'no-referrer'로 설정되어 있으며 이는 참조 정보가 전송되지 않음을 의미합니다.
웹사이트에 HTTPS를 사용하도록 합니다. 기본값은 'max-age=15552000; includeSubDomains'는 브라우저가 지정된 최대 연령 동안만 HTTPS를 사용하여 웹사이트에 연결하고 모든 하위 도메인을 포함해야 함을 의미합니다.
브라우저가 파일의 MIME 유형을 추측하고 잠재적으로 악성 코드를 실행하는 것을 방지합니다. 기본값은 'nosniff'로 설정되어 있습니다.
브라우저의 DNS 프리페치를 제어합니다.
기본값은 '꺼짐'으로 설정되어 있습니다.
Internet Explorer가 사이트 컨텍스트에서 다운로드를 실행하지 못하도록 합니다.
기본값은 '아니오'로 설정되어 있습니다.
프레임에 페이지를 표시하지 않도록 브라우저에 지시하여 클릭재킹 공격을 방지합니다.
기본값은 'SAMEORIGIN'으로 설정되며 이는 페이지가 페이지와 동일한 출처의 프레임에만 표시될 수 있음을 의미합니다.
Adobe Flash 플레이어의 도메인 간 정책 파일에 대한 정책을 설정합니다.
기본값은 도메인 간 정책 파일이 허용되지 않음을 의미하는 '없음'으로 설정됩니다.
브라우저의 내장 XSS 보호를 활성화합니다.
기본값은 XSS 필터를 비활성화하는 '0'으로 설정됩니다.
위의 12가지 기본제공 옵션의 default값을 수정하여 기본옵션의 기본값 변경과 활성화 상태 변경이 가능하다.
app.use(helmet({ contentSecurityPolicy: false, << 기본옵션 중 이 옵션만 비활성화 })
위의 기본헤더를 기본값 외에도 helmet은 추가적인 변경옵션들을 제공한다.
helmet.contentSecurityPolicy(옵션)
Content-Security-Policy 헤더를 설정하여 웹 페이지에서 로드할 수 있는 콘텐츠 소스를 정의하여 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격(injection)을 방지합니다. 이 헤더를 사용하면 스크립트, 스타일, 이미지 및 글꼴과 같은 리소스를 로드할 수 있는 원본과 로드 방법을 지정할 수 있습니다. 또한 오류가 발생한 경우 콘텐츠의 대체 소스를 지정할 수 있습니다.
helmet.crossOriginEmbedderPolicy(옵션)
다른 출처의 페이지에서 리소스를 로드할 수 있는지 여부를 제어하는 Cross-Origin-Embedder-Policy 헤더를 설정합니다. 이 헤더를 사용하면 페이지가 다른 출처의 리소스를 삽입할 수 있는지 여부를 지정할 수 있으며 클릭재킹 공격을 방지하는 데 사용할 수 있습니다.
helmet.crossOriginOpenerPolicy()
다른 출처의 링크로 페이지를 열 수 있는지 여부를 제어하는 Cross-Origin-Opener-Policy 헤더를 설정합니다. 이 헤더를 사용하면 다른 원본의 링크로 페이지를 열 수 있는지 여부를 지정할 수 있으며 tabnabbing 공격을 방지하는 데 사용할 수 있습니다.
helmet.crossOriginResourcePolicy()
다른 출처의 페이지에서 리소스를 로드할 수 있는지 여부를 제어하는 Cross-Origin-Resource-Policy 헤더를 설정합니다. 이 헤더를 사용하면 페이지가 다른 원본에서 리소스를 로드할 수 있는지 여부를 지정할 수 있으며 XSS(교차 사이트 스크립팅) 및 기타 코드 주입 공격을 방지하는 데 사용할 수 있습니다.
helmet.dnsPrefetchControl(옵션)
브라우저가 페이지의 링크에 대한 DNS 정보를 미리 가져올 수 있는지 여부를 제어하는 X-DNS-Prefetch-Control 헤더를 설정합니다. 이 헤더를 사용하면 DNS 정보를 미리 가져오는 브라우저의 기능을 비활성화하여 페이지 로드 시간을 개선하고 사용되는 데이터 양을 줄일 수 있습니다.
helmet.expectCt(옵션)
사이트에 대한 유효한 인증서 투명성 정보를 예상하도록 브라우저에 알려주는 Expect-CT 헤더를 설정합니다. 이 헤더를 사용하면 브라우저가 이 정보를 캐시해야 하는 최소 시간과 정보가 유효하지 않은 경우 전송해야 하는 report-uri를 지정할 수 있습니다.
helmet.frameguard(옵션)
<frame>
, <iframe>
또는 <object>
에 페이지를 로드할 수 있는지 여부를 제어하는 X-Frame-Options 헤더를 설정합니다. 이 헤더를 사용하면 페이지를 프레임에 로드할 수 있는지 여부를 지정할 수 있으며 클릭재킹 공격을 방지하는 데 사용할 수 있습니다.
helmet.hidePoweredBy()
사용 중인 서버 소프트웨어를 식별하는 데 사용할 수 있는 X-Powered-By 헤더를 제거합니다. 이 헤더를 사용하면 사용 중인 서버 소프트웨어를 숨길 수 있으므로 공격자가 해당 소프트웨어에 특정한 취약점을 찾기가 더 어려워질 수 있습니다.
helmet.hsts()
사이트에 대해 HTTPS를 사용하도록 브라우저에 지시하는 Strict-Transport-Security 헤더를 설정합니다. 이 헤더를 사용하면 브라우저가 사이트에 대해 HTTPS를 사용해야 하는 최소 시간을 지정할 수 있으며 메시지 가로채기(man-in-the-middle) 공격을 방지하는 데 사용할 수 있습니다.
helmet.ieNoOpen()
사이트 컨텍스트에서 사이트에서 다운로드한 파일을 열지 않도록 Internet Explorer에 지시하는 X-Download-Options 헤더를 설정합니다. 이 헤더는 Internet Explorer에만 해당되며 사이트 컨텍스트에서 파일이 열리지 않도록 하는 데 사용할 수 있습니다. 이는 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격을 방지하는 데 사용할 수 있습니다.
helmet.noSniff()
X-Content-Type-Options 헤더를 설정하여 브라우저가 파일의 MIME 유형을 추측하지 않도록 합니다. 이 헤더를 사용하면 브라우저가 파일의 MIME 유형을 추측하지 않도록 지정하고 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격을 방지하는 데 사용할 수 있습니다.
helmet.originAgentCluster()
원본 에이전트의 클러스터 이름을 포함하도록 Server 헤더를 설정합니다. 이 헤더를 사용하면 디버깅 및 문제 해결에 유용할 수 있는 서버 헤더에 원본 에이전트의 클러스터 이름을 포함할 수 있습니다.
helmet.permittedCrossDomainPolicies(옵션)
허용되는 도메인 간 정책을 제어하는 X-Permitted-Cross-Domain-Policies 헤더를 설정합니다. 이 헤더를 사용하면 허용되는 도메인 간 정책을 지정할 수 있으며 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격을 방지하는 데 사용할 수 있습니다.
helmet.referrerPolicy(옵션)
Referer 헤더에서 전송되는 정보의 양을 제어하는 Referrer-Policy 헤더를 설정합니다. 이 헤더를 사용하면 Referer 헤더에 보낼 정보의 양을 지정할 수 있으며 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격을 방지하는 데 사용할 수 있습니다.
helmet.xssFilter()
브라우저의 XSS 필터링을 활성화하는 X-XSS-Protection 헤더를 설정합니다. 이 헤더를 사용하면 XSS(교차 사이트 스크립팅) 및 기타 코드 삽입 공격을 방지하는 데 도움이 되는 브라우저의 기본 제공 XSS 필터링을 활성화할 수 있습니다.
위의 추가 변경된 옵션들을 적용하기 위해서는 아래와 같이 사용한다.
app.use(helmet.expectCt({maxAge: 86400}), helmet.xssFilter())
위의 사용방법과 다음과 같이도 사용할 수 있다.
app.use(helmet({ referrerPolicy: { policy: "no-referrer" }, frameguard:{action:"deny"}, expectCt:{maxAge: 86400, enforce: true, reportUri: "https://example.com/report"}, contentSecurityPolicy: false, << 기본옵션 중 이 옵션만 비활성화 })
다면 이렇게 옵션을 따로 설정해 준다면 기본 app.user(helmet())으로 사용할 때 적용되던 기본값헤드들이 적용되지 않고,
옵션설정한 헤더만 적용되니, 되도록 옵션설정을 하나 바꾸게 된다면 일일이 다 옵션을 적어줘야 할 필요성이 생길 것 같다.
helmet은 미들웨어 기능의 모음이기 때문에 각 미들웨어를 별로도 작성해 넣어줘야 하며, 순서 또한 중요하게 생각해야 된다고 한다. 내가 적용할 helmet의 기능을 올바른 순서로 적용하고 있는지 확인해가며 작성해야 한다.
웹 브라우저에서 구글링해보면 현재 helmet 공식 페이지에 나와있지 않은 다른 옵션들의 적용사례를 발견할 수 있다. 이게 이전 버전에서 적용되었던 것인지, 아직 적용할 수 있는 것인지, 버전이 바뀌면서 병합되어 다른 옵션과 같이 들어가는지는 알 수 없다.
helmet.featurePolicy(): Feature-Policy브라우저가 사이트에 허용해야 하는 기능과 API를 제어하는 헤더를 설정합니다.
helmet.reportTo(): Report-To위반 보고서를 보낼 위치를 브라우저에 알려주는 헤더를 설정합니다.
helmet.reportUri(): Report-URI위반 보고서를 보낼 위치를 브라우저에 알려주는 헤더를 설정합니다.
helmet.useStrictTransportSecurity(): Strict-Transport-Security웹사이트에 HTTPS 사용을 강제하는 헤더를 설정합니다.
helmet.noCache(): Cache-Control및 Pragma헤더를 no-cache로 설정하여 응답의 클라이언트 측 캐싱을 비활성화합니다. (v5 부터 사라짐)
helmet.hpkp(): Public-Key-Pins사이트에 대한 HPKP(HTTP Public Key Pinning)를 구성할 수 있는 헤더를 설정합니다.
아직 개발초보인 내겐 솔직하게 내용이 방대하고, 전혀 모르는 용어들이 난무하며, 현재 내 프로젝트에 적용해야할 옵션이 무엇인지 일일이 매칭하는게 안된다. 각 헤더가 무슨 역할을 하는지 하나씩 알아봐야 하고, 그에 따른 옵션선택을 구상하며, 그 옵션을 적용하는 방법에 대해서 또 생각해봐야하니 너무 어려운 것 같다.
그냥 누가 시원하게 우리프로젝트에 어떤어떤 옵션을 적용해야 하지는 가르쳐 줬으면 좋겠다. 아니면...보통 대부분 많은 프로젝트에서 적용하는 통상적인 옵션이라도.... ㅠㅠ