본문 바로가기

Node.js

node.js - 보안 모범 사례

개요
"프로덕션"이라는 용어는 소프트웨어 수명 주기에서 애플리케이션 또는 API를 최종 사용자 또는 소비자가 일반적으로 사용할 수 있는 단계를 의미합니다. 이와는 대조적으로 '개발' 단계에서는 여전히 코드를 작성하고 테스트하는 중이며 애플리케이션이 외부에 공개되지 않습니다. 해당 시스템 환경을 각각 프로덕션 환경과 개발 환경이라고 합니다.

개발 환경과 프로덕션 환경은 일반적으로 다르게 설정되며 요구 사항이 크게 다릅니다. 개발 환경에서는 괜찮은 것이 프로덕션 환경에서는 허용되지 않을 수 있습니다. 예를 들어 개발 환경에서는 디버깅을 위해 오류에 대한 자세한 로깅을 원할 수 있지만 프로덕션 환경에서는 동일한 동작이 보안 문제가 될 수 있습니다. 또한 개발 환경에서는 확장성, 안정성, 성능에 대해 걱정할 필요가 없지만 프로덕션 환경에서는 이러한 문제가 중요해집니다.

 

더 이상 사용되지 않거나 취약한 버전의 Express를 사용하지 마세요.

Express 2.x 및 3.x는 더 이상 유지 관리되지 않습니다. 

이러한 버전의 보안 및 성능 문제는 수정되지 않습니다. 사용하지 마세요! 

아직 버전 4로 마이그레이션하지 않았다면 마이그레이션 가이드를 따르세요.

 

또한 보안 업데이트 페이지에 나열된 취약한 Express 버전을 사용하고 있지 않은지 확인하세요.

사용 중이라면 안정적인 버전 중 하나로 업데이트하세요(가급적 최신 버전).

 

TLS 사용

앱에서 민감한 데이터를 처리하거나 전송하는 경우, TLS(전송 계층 보안)를 사용하여 연결과 데이터를 보호하세요. 이 기술은 데이터를 클라이언트에서 서버로 전송하기 전에 암호화하여 일반적인(그리고 쉬운) 해킹을 방지합니다. Ajax 및 POST 요청은 눈에 띄지 않고 브라우저에서 "숨겨진" 것처럼 보일 수 있지만, 해당 네트워크 트래픽은 패킷 스니핑 및 중간자 공격에 취약합니다.

 

보안 소켓 계층(SSL) 암호화에 익숙하실 것입니다. TLS는 SSL의 다음 단계에 불과합니다. 즉, 이전에 SSL을 사용 중이었다면 TLS로 업그레이드하는 것을 고려하세요. 일반적으로 TLS를 처리하는 데는 Nginx를 권장합니다. Nginx(및 기타 서버)에서 TLS를 구성하는 데 좋은 참고 자료는 권장 서버 구성(Mozilla Wiki)을 참조하세요.

 

또한 무료 TLS 인증서를 받을 수 있는 편리한 도구로는 인터넷 보안 연구 그룹(ISRG)에서 제공하는 자동화된 무료 개방형 인증 기관(CA)인 Let's Encrypt가 있습니다.

 

Helmet 사용

Helmet은 HTTP 헤더를 적절히 설정하여 잘 알려진 웹 취약점으로부터 앱을 보호하는 데 도움이 될 수 있습니다.

Helmet은 보안 관련 HTTP 응답 헤더를 설정하는 여러 가지 작은 미들웨어 함수의 모음입니다. 몇 가지 예는 다음과 같습니다:

  • Content-Security-Policy 헤더를 설정하는 helmet.contentSecurityPolicy.
    • 이는 다른 많은 것들 중에서도 크로스 사이트 스크립팅 공격을 방지하는 데 도움이 됩니다.
  • Helmet.hsts - Strict-Transport-Security 헤더를 설정합니다.
    • 이는 서버에 대한 보안(HTTPS) 연결을 강화하는 데 도움이 됩니다.
  • Helmet frameguard - X-Frame-Options 헤더를 설정합니다.
    • 이는 클릭재킹 방지를 제공합니다.

 

Helmet에는 문서 웹사이트에서 확인할 수 있는 다른 여러 미들웨어 기능이 포함되어 있습니다.

다른 모듈과 마찬가지로 Helmet을 설치합니다

$ npm install --save helmet

 

다음 코드를 사용

// ...

const helmet = require('helmet')
app.use(helmet())

// ...

 

 

Fingerprinting 감소

Server Fingerprinting을 줄이기 위해 추가적인 보안 계층을 제공하는 것이 도움이 될 수 있습니다.

보안 문제 자체는 아니지만 웹 서버의 전반적인 상태를 개선하는 방법은 서버에서 사용 중인 소프트웨어의 Fingerprinting 기능을 줄이는 조치를 취하는 것입니다.

서버 소프트웨어는 특정 요청에 응답하는 방식에 의해 Fingerprinting될 수 있습니다.

기본적으로 Express.js는 X-Powered-By 응답 헤더 배너를 보냅니다. 이 기능은 app.disable() 메서드를 사용하여 비활성화할 수 있습니다:

app.disable('x-powered-by')

참고: X-Powered-By 헤더를 비활성화해도 정교한 공격자가 앱이 Express를 실행 중인지 확인하는 것을 막을 수는 없습니다. 일반적인 익스플로잇은 막을 수 있지만, 앱이 Express를 실행 중인지 확인하는 다른 방법도 있습니다.

 

또한 Express.js는 자체 형식의 404 찾을 수 없음 메시지와 자체 포맷터 오류 응답 메시지를 전송합니다. 이러한 메시지는 자체 찾을 수 없음 핸들러를 추가하고 자체 오류 핸들러를 작성하여 변경할 수 있습니다:

// last app.use calls right before app.listen():

// custom 404
app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!")
})

// custom error handler
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

 

쿠키를 안전하게 사용

쿠키로 인해 앱이 익스플로잇에 노출되지 않도록 하려면 기본 세션 쿠키 이름을 사용하지 말고 쿠키 보안 옵션을 적절히 설정하세요.

 

두 가지 주요 미들웨어 쿠키 세션 모듈이 있습니다:

  • Express 3.x에 내장된 express.session 미들웨어를 대체하는 express-session.
  • Express 3.x에 내장된 express.cookieSession 미들웨어를 대체하는 cookie-session.

 

이 두 모듈의 주요 차이점은 쿠키 세션 데이터를 저장하는 방식입니다. express-session 미들웨어는 서버에 세션 데이터를 저장하지만, 세션 데이터는 저장하지 않고 쿠키 자체에 세션 ID만 저장합니다. 기본적으로 인메모리 스토리지를 사용하며 프로덕션 환경용으로 설계되지 않았습니다. 프로덕션 환경에서는 확장 가능한 세션 저장소를 설정해야 합니다(호환 가능한 세션 저장소 목록 참조).

반면 쿠키 세션 미들웨어는 쿠키 기반 스토리지를 구현하며, 세션 키가 아닌 전체 세션을 쿠키에 직렬화합니다. 세션 데이터가 상대적으로 작고 객체가 아닌 원시 값으로 쉽게 인코딩할 수 있는 경우에만 사용합니다. 브라우저는 쿠키당 최소 4096바이트를 지원하도록 되어 있지만, 한도를 초과하지 않도록 도메인당 4093바이트 크기를 초과하지 않도록 하세요. 또한 쿠키 데이터는 클라이언트에 표시되므로 보안을 유지하거나 모호하게 유지해야 할 이유가 있는 경우 익스프레스 세션이 더 나은 선택일 수 있습니다.

 

기본 세션 쿠키 이름 사용하지 않기

기본 세션 쿠키 이름을 사용하면 앱이 공격에 노출될 수 있습니다. 잠재적인 공격자가 이 쿠키를 사용하여 서버를 핑거프린팅하고 그에 따라 공격을 타겟팅할 수 있다는 점에서 보안 문제가 발생할 수 있습니다.

이 문제를 방지하려면 일반 쿠키 이름(예: 익스프레스 세션 미들웨어 사용)을 사용하세요:

쿠키 보안 옵션 설정

보안을 강화하려면 다음 쿠키 옵션을 설정하세요:

보안 - 브라우저가 HTTPS를 통해서만 쿠키를 전송하도록 합니다.
httpOnly - 쿠키가 클라이언트 자바스크립트가 아닌 HTTP(S)를 통해서만 전송되도록 하여 크로스 사이트 스크립팅 공격으로부터 보호합니다.
도메인 - 쿠키의 도메인을 나타내며, URL이 요청되는 서버의 도메인과 비교하는 데 사용합니다. 일치하면 다음 경로 속성을 확인합니다.
경로 - 쿠키의 경로를 나타내며 요청 경로와 비교하는 데 사용합니다. 이 값과 도메인이 일치하면 요청에 쿠키를 전송합니다.
expires - 영구 쿠키의 만료일을 설정하는 데 사용합니다.
다음은 쿠키 세션 미들웨어를 사용한 예시입니다:

const session = require('cookie-session')
const express = require('express')
const app = express()

const expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
  name: 'session',
  keys: ['key1', 'key2'],
  cookie: {
    secure: true,
    httpOnly: true,
    domain: 'example.com',
    path: 'foo/bar',
    expires: expiryDate
  }
}))

 

인증에 대한 무차별 암호 대입 공격 방지

로그인 엔드포인트가 보호되어 있는지 확인하여 개인 데이터를 더욱 안전하게 보호하세요.

간단하고 강력한 기술은 두 가지 지표를 사용하여 인증 시도를 차단하는 것입니다:

첫 번째는 동일한 사용자 이름과 IP 주소로 인증 시도에 연속적으로 실패한 횟수입니다.

두 번째는 일정 기간 동안 한 IP 주소에서 실패한 시도 횟수입니다. 예를 들어, 하루에 100번의 시도가 실패하면 해당 IP 주소를 차단합니다.
속도 제한 유연성 패키지는 이 기법을 쉽고 빠르게 수행할 수 있는 도구를 제공합니다. 무차별 암호 대입 보호의 예는 다음 문서에서 확인할 수 있습니다.

 

종속성의 보안 보장

npm을 사용하여 애플리케이션의 종속성을 관리하는 것은 강력하고 편리합니다. 하지만 사용하는 패키지에 애플리케이션에도 영향을 줄 수 있는 심각한 보안 취약점이 포함되어 있을 수 있습니다. 앱의 보안은 종속성에서 "가장 약한 링크"만큼만 강력합니다.

npm@6부터 npm은 모든 설치 요청을 자동으로 검토합니다. 또한 'npm audit'를 사용하여 의존성 트리를 분석할 수 있습니다.

$ npm audit

보안을 더욱 강화하려면 Snyk를 고려하세요.

Snyk는 명령줄 도구와 Github 통합을 모두 제공하여 애플리케이션의 종속성에 알려진 취약점이 있는지 Snyk의 오픈 소스 취약성 데이터베이스와 비교하여 검사합니다. 다음과 같이 CLI를 설치합니다:

$ npm install -g snyk
$ cd your-app

이 명령을 사용하여 애플리케이션의 취약점을 테스트하세요:

$ snyk test

이 명령을 사용하면 발견된 취약점을 수정하기 위해 업데이트 또는 패치를 적용하는 과정을 안내하는 마법사를 열 수 있습니다:

$ snyk wizard

 

기타 알려진 취약점 피하기

앱에서 사용하는 Express 또는 기타 모듈에 영향을 줄 수 있는 Node Security Project 또는 Snyk 권고 사항을 주시하세요. 일반적으로 이러한 데이터베이스는 노드 보안에 대한 지식과 도구에 대한 훌륭한 리소스입니다.

마지막으로, 다른 웹 앱과 마찬가지로 Express 앱도 다양한 웹 기반 공격에 취약할 수 있습니다. 알려진 웹 취약점을 숙지하고 이를 방지하기 위한 예방 조치를 취하세요.

 

추가 고려 사항

다음은 훌륭한 Node.js 보안 체크리스트의 몇 가지 추가 권장 사항입니다.

  • 항상 사용자 입력을 필터링하고 살균하여 크로스 사이트 스크립팅(XSS) 및 명령어 인젝션 공격으로부터 보호하세요.
  • 매개변수화된 쿼리 또는 준비된 문을 사용하여 SQL 인젝션 공격을 방어하세요.
  • 오픈 소스 sqlmap 도구를 사용하여 앱의 SQL 인젝션 취약점을 탐지하세요.
  • nmap 및 sslyze 도구를 사용하여 SSL 암호, 키 및 재협상의 구성과 인증서의 유효성을 테스트하세요.
  • 정규 표현식이 정규 표현식 서비스 거부 공격에 취약하지 않은지 확인하려면 안전 정규 표현식을 사용하세요.

'Node.js' 카테고리의 다른 글

JavaScript의 즉시 실행 함수(IIFE)  (0) 2023.05.22
PM2  (0) 2023.05.01
node.js - 프로세스 매니저  (0) 2023.04.24
AICodeHelper  (0) 2023.04.11
Node.js AWS S3 파일 업로드  (0) 2023.04.07