댓글 검색 목록

[javascript] JavaScript 및 Node.js에서 코드 삽입을 방지하는 5 가지 방법

페이지 정보

작성자 운영자 작성일 21-04-14 09:39 조회 1,235 댓글 0

코드 삽입을 방지하는 방식으로 보안 코드를 작성하는 것은 평범한 작업처럼 보일 수 있지만 그 과정에는 많은 함정이 있습니다. 예를 들어 귀하 (개발자)가 최고의 보안 관행을 따른다는 사실이 다른 사람들도 똑같이 하고 있다는 것을 의미하지는 않습니다. 애플리케이션에서 오픈 소스 패키지를 사용하고 있을 가능성이 높습니다. 그것들이 안전하게 개발되었는지 어떻게 알 수 있습니까? eval ()과 같은 안전하지 않은 코드가 있으면 어떻게 됩니까? 자세히 살펴 보겠습니다.


코드 삽입이란 무엇입니까? 


코드 삽입은 공격자가 브라우저 또는 Node.js 런타임에 의해 해석되는 JavaScript 또는 Node.js 코드를 보낼 수 있는 광범위한 삽입 공격의 특정 형태입니다. 보안 취약점은 인터프리터가 개발자가 의도 한 신뢰할 수 있는 코드와 공격자가 입력으로 제공 한 삽입 된 코드를 구분할 수 없을 때 나타납니다.


코드 삽입을 방지하는 방법 


주요 보안 코딩 규칙으로 애플리케이션에서 동적 코드 실행을 허용하지 마십시오. 즉, setTimeout() 또는 Function 생성자에 전달되는 eval 및 코드 문자열과 같은 언어 구성을 피해야 합니다. 둘째, 직렬화 프로세스에서 코드를 실행하는 주입 공격에 취약 할 수 있는 직렬화를 피하십시오. 마지막으로, 애플리케이션이 타사 오픈 소스 구성 요소로 인해 이 공격에 취약하지 않도록 종속성 검사를 수행합니다. 또한 Snyk Code와 같은 정적 코드 분석 도구를 사용하는 경우 사용자 또는 동료의 코드에서 이러한 잠재적 인 코드 삽입 보안 취약성을 찾을 수 있습니다.


이 기사에서는 코드 삽입을 방지하는 5 가지 방법을 살펴볼 것입니다.

  1. eval(), setTimeout() 및 setInterval()을 피하십시오.
  2. new Function() 피하기
  3. JavaScript에서 코드 직렬화 방지
  4. Node.js 보안 린터 사용
  5. 정적 코드 분석 (SCA) 도구를 사용하여 코드 삽입 문제를 찾고 수정합니다.

1. eval(), setTimeout() 및 setInterval()을 피하십시오. 


여러분의 생각을 알고 있습니다. 여기에 평가를 피하라고 알려주는 또 다른 가이드가 있습니다. 예, 맞습니다.하지만 eval (또는 다른 형태의 코드 구성)을 사용한 다른 인기 라이브러리의 실제 사례도 제공하고 싶습니다.이 라이브러리는 다시 공격하여 심각한 보안 취약성을 유발합니다.


하지만 취약한 타사 패키지 참조를 살펴보기 전에 먼저 eval 및 이에 수반되는 기능에 대해 설명하겠습니다. 브라우저 및 서버 측 Node.js 플랫폼과 같은 JavaScript 런타임 환경에서는 런타임 중에 코드를 평가하고 실행할 수 있습니다. 이에 대한 실제 예는 다음과 같습니다.


const getElementForm = getElementType == “id” ? “getElementById” : “getElementByName”;
const priceTagValue = eval(“document.”+getElementForm+”(“+elementId+”).value”);


이를 통해 프로그래머는 DOM의 데이터에 액세스하는 동적 인 방법을 만들려고 합니다. 이 예에서는 getElementform이 elementId 변수뿐만 아니라 잠재적으로 사용자가 제어 할 수도 있다고 가정합니다. eval없이 이 작업을 수행하는 더 좋은 방법이 있으므로 반드시 이와 같은 동적 코드를 피해야 합니다.


Node.js 측에서는 일부 동적 평가를 기반으로 애플리케이션의 특정 데이터 포인트에 대한 액세스를 허용 할 수 있습니다. 예를 들면 다음과 같습니다.


const db = "./db.json"
const dataPoints = eval("require('"+db+"')");


이 예에서 일반적인 가정은 필요한 정확한 파일이 동적이며 잠재적으로 사용자가 제어 할 수 있다는 것입니다.이 경우에도 잠재적 인 코드 삽입 보안 취약성이 있습니다.


Dustjs 코드 삽입은 안전하지 않은 평가 사용의 실제 예를 보여줍니다. 


LinkedIn의 npm 패키지 dustjs (브라우저 및 서버 측 Node.js 용 비동기 템플릿 프로젝트)는 코드 삽입 취약점이 얼마나 심각해질 수 있는지 보여줍니다.


이 패키지는 더 이상 유지 관리가 잘되지 않지만 월간 다운로드 수는 약 72,000 건이며 코드 삽입 보안 취약점을 처리해야 했습니다.


dustjs의 관리자는 eval () 함수와 같은 안전하지 않은 코드 구조로 유입 될 수 있는 잠재적으로 위험한 사용자 입력을 피하기 위해 최선을 다했지만 escapeHtml 함수 자체에는 문자열 유형 만 확인한 다음 입력을 이스케이프하는 보안 결함이 있습니다. , 배열과 같은 다른 유형도 확인해야 합니다. 이 풀 요청은 코드 삽입 보안 취약점을 수정했습니다.


This pull request fixed the code injection security vulnerability 

eval()이이 모든 질문에 어떻게 들어 맞습니까?


dustjs를 사용하는 경우 npm 패키지 dustjs-helpers를 도입하여 수학 연산 및 논리 연산과 같은 추가 템플릿 도우미를 얻을 수도 있습니다. 이러한 추가 도우미 중 하나는 if 조건으로, 자신의 먼지 템플릿 파일에서 다음과 같이 사용할 수 있습니다.


Configure your own dust template 


말이 되죠?


문제는 쿼리 매개 변수 장치의 제어되지 않은 사용자 입력이 227 행에서 볼 수 있듯이 eval을 사용하여 조건을 동적으로 평가하는 if 조건 도우미로 직접 흐른다는 것입니다.


Watch out for uncontrolled user input 


이제 모든 것이 명확 해지고 몇 가지 보안 문제가 예상치 못한 방식으로 결합되는 방식을 보여줍니다.


오픈 소스 패키지 인 dustjs-linkedin에는 escapeHtml 함수의 입력 문자열이 잘못 삭제 된 보안 결함이 있습니다.

오픈 소스 패키지 인 dustjs-helpers는 eval() 함수와 같은 안전하지 않은 코딩 규칙을 사용하여 런타임에 코드를 동적으로 평가합니다.


이 취약점을 어떻게 악용하고 정확히 이 취약점을 기반으로 실제 작동 중인 응용 프로그램을 해킹했는지 보고 싶습니까? 확인 해봐:



또한 setTimeout() 및 setInterval()을 피하십시오. 


eval()을 피하는 모범 사례를 마무리하기 위해 JavaScript 개발자로서 응용 프로그램에서 가장 확실하게 들어 보거나 적어도 한 번은 사용한 적이 있는 다른 함수 인 setTimeout() 및 setInterval()을 호출하고 싶습니다.


이 함수에 대해 잘 알려지지 않은 사실은 코드 문자열도 수신한다는 것입니다. 예를 들어 다음과 같이 사용할 수 있습니다.


setTimeout(“console.log(1+1)”, 1000);


다행히도 Node.js 환경에서는 문자열 리터럴이 허용되지 않습니다!


2. Avoid new Function() 


위의 eval(), setTimeout() 및 setInterval()과 유사한 또 다른 언어 구조는 문자열 리터럴을 기반으로 함수를 동적으로 정의 할 수 있는 Function 생성자입니다.


다음과 같은 평범한 예를 고려하십시오.


const addition = new Function(‘a’, ‘b’, ‘return a+b’);
addition(1, 1)


지금까지 자세히 살펴보면 이러한 기능으로 유입되는 사용자 입력에서 발생할 수 있는 잠재적 인 보안 문제를 이미 알고 있는 것입니다.


3. JavaScript에서 코드 직렬화 방지 


직렬화는 Java 생태계에서 상당히 중요한 일입니다. 내 친구 Brian Vermeer는 보안 취약성이 안전하지 않은 직렬화 작업으로 인해 Java 애플리케이션에 미치는 영향에 대한 블로그 게시물을 작성했습니다. 나는 그것을 읽을 것을 강력히 추천합니다 : Java의 직렬화 및 직렬화 해제 : Java deserialize 취약점을 설명합니다.


JavaScript 세계로 돌아 가면 분명히 직렬화도 문제입니다.


자신의 직렬화 및 역 직렬화 논리를 직접 코딩하지 않을 가능성이 있지만 npm과 1,500,000 개 이상의 오픈 소스 패키지를 마음대로 사용할 수 있는 멋진 세계에서 사용하지 않는 이유는 무엇입니까?


js-yaml은 주당 28,000,000 회 이상의 다운로드로 인기를 얻고 있으며 Snyk Advisor에 따르면 전반적인 패키지 상태가 양호합니다.


blog-prevent-code-injection-js-waml-health.png 


즉, 위의 npm 패키지 js-yaml 스크린 샷에서 이전 버전에 보안 취약성이 있음을 알 수 있습니다. 어느 쪽을 물어?


js-yaml 버전은 역 직렬화로 인해 코드 실행에 취약한 것으로 확인되었습니다. 취약점이 나타나는 방식은 다음과 같은 new Function() 생성자 사용 때문입니다.


function resolveJavascriptFunction(object /*, explicit*/) {
  /*jslint evil:true*/
  var func;

  try {
    func = new Function('return ' + object);
    return func();
  } catch (error) {
    return NIL;
  }
}


이 취약점에 대한 개념 증명 악용이 어떻게 생겼는지 살펴 보겠습니다.


var yaml = require('js-yaml'); x = "test: !!js/function > \n \ function f() { \n \ console.log(1); \n \ }();" yaml.load(x);



따라서 악의적 인 행위자가 위의 개념 증명 코드에서 x 변수를 생성하는 데 사용되는 입력 또는 그 일부를 제공 할 수 있다면 잠재적 인 취약점이 실제 위험이 됩니다.


위의 취약점은 2013 년으로 거슬러 올라가지 만 2019 년 보안 취약점 보고서에서 js-yaml에서 임의 코드 실행의 또 다른 사례가 발견되었습니다. 따라서 조심하거나 더 실행 가능하고 실용적인 조언을 제공하십시오. new Function()을 피하고 실제로 타사 오픈 소스 패키지를 스캔하여 이러한 취약점이 없는지 확인하고 문제가 있는 경우 수정할 수 있는지 확인하십시오. 수정 풀 요청으로 자동으로


4. Node.js 보안 linter 사용 


이 가이드의 툴링 부분에 이르러 린터에 대해 이야기 해 보겠습니다. 자바 스크립트 개발자는 린터를 좋아합니다. 코드 스타일을 적용하기 위해 standardjs를 사용하든 eslint를 사용하든 이는 모든 JavaScript 또는 Node.js 프로젝트에서 매우 일반적인 도구입니다.


좋은 보안 관행을 시행하지 않는 이유는 무엇입니까? 이것은 eslint-plugin-security가 파티에 참여하는 곳입니다. README 지침에 따라 플러그인을 사용하는 것은 매우 간단합니다. 권장 구성을 활성화하려면 다음 eslint 플러그인 구성을 추가하기 만하면 됩니다.


"plugins": [
  "security"
],
"extends": [
  "plugin:security/recommended"


linter는 어떻게 도움이 됩니까?


다음과 같은 안전하지 않은 코딩 규칙을 감지하는 규칙이 있습니다. detect-eval-with-expression – 표현식 또는 문자열 리터럴과 함께 eval()의 사용을 감지합니다. linter는 child_process Node.js API 사용과 같은 다른 규칙입니다.


eslint-plugin-security는 4 년 전의 마지막 게시 날짜를 가지고 있으며 여전히 기능적으로 잘 작동 할 수 있지만 eslint-plugin-security-node와 같은 다른 후속 패키지를 고려할 수 있습니다.


5. 정적 코드 분석 도구를 사용하여 코드 삽입 문제를 찾고 수정합니다. 


ESLint와 함께 사용되는 기본 형태의 정적 코드 분석 (SCA) linter는 좋은 시작점입니다. 코드 스타일을 적용하기에 충분한 컨텍스트를 제공하지만 Node.js 보안 린터에서 살펴본 것처럼 실제로 보안 문제를 해결하는 데 필요한 만큼 유연하지 않습니다.


eslint-plugin-security와 같은 Node.js 보안 린터에 대한 개발자의 우려 사항 중 일부는 다음과 같습니다.


  1. False positives : 린터 규칙은 매우 기본적이며 개발자의 불만과 혼란을 유발하는 많은 오 탐지에 대해 경고 할 수 있습니다. 예를 들어 다음 RegExp (matchEmailRegEx)는 RegExp 함수를 비문 자적으로 사용하기 때문에 Node.js 보안 linter에 오류를 발생시킵니다. 아마도 matchEmailRegEx는 내 shared/variables.js 파일의 상수일까요? 린 터는 그것을 알만큼 충분히 발전되지 않았습니다.
  2. Rules are too rigid : 위의 요점에 계속해서 규칙이 너무 엄격합니다. child_process.exec (someCommand, [])를 사용하거나 사용하지 않습니다. linter와 함께 사용되는 정적 코드 분석 프로세스는 someCommand가 하드 코딩 된 상수라고 말할만큼 똑똑하지 않습니다. 비 리터럴에서 child_process.exec ()를 사용하고 있다는 사실은 linter 오류를 트리거하기에 충분하며 결국 규칙을 해제하는 개발자에게 좌절감을 안겨줍니다.
  3. Rules are too basic. 규칙 모음이 너무 작고 결과가 너무 기본적입니다. 기본적으로 주어진 사용자 입력에서 명령 실행, SQL 쿼리 등과 같은 잠재적 인 민감한 코드로 데이터가 실제로 어떻게 흐르는 지에 대한 많은 컨텍스트 없이는 전부 또는 전혀 없습니다.

이전의 문장을 반복하려면 eslint-plugin-security-node 또는 기타와 같은 보안 린터가 좋은 시작점입니다. 전혀 없는 것보다 확실히 낫습니다.


그러나 코딩하는 동안 자신의 코드에서 보안 문제를 찾는 더 좋은 방법이 있습니다.


개발자를 위해 구축 된 정적 SAST (애플리케이션 보안 테스트 도구) 인 Snyk Code를 소개하겠습니다.


Node.js 애플리케이션에서 명령 주입 찾기 


Snyk 코드가 곧 출시 될 예정이지만 작동 방식에 대해 간략히 소개하겠습니다.


먼저 GitHub 계정으로 Snyk에 연결 한 다음 GitHub 리포지토리를 가져옵니다. 이렇게 하려면 프로젝트 추가를 클릭 한 다음 GitHub 아이콘을 클릭합니다.


Add a GitHub repository to Snyk Code with a click. 


그런 다음 저장소 목록에서 저장소를 찾거나 검색 상자를 사용하여 입력 한 다음 저장소를 전환하여 스캔을 시작합니다.


Import GitHub repository to scan for security issues 


그러면 Snyk는 GitHub 저장소를 가져 와서 빠르게 스캔합니다.


알려진 취약성이 있는 오픈 소스 종속성을 사용하거나 Docker 이미지가 보안 취약성을 유발하는 경우와 같이 잠재적 보안 문제와 관련된 다른 매니페스트 파일을 자동으로 감지합니다.


이 Node.js 애플리케이션의 자체 코드에 초점을 맞춰 코드 분석을 클릭하고 찾은 내용을 살펴 보겠습니다.


Easily analyze Node.js application code from Snyk Code 


Snyk Code는 몇 가지 취약점을 발견했으며 그중 하나는 다음과 같이 명령 주입입니다.


blog-prevent-code-injection-vulnerabilities-1.png 


이 코드 줄에서 발견 된 문제가 있는 보안 문제에 대한 설명은 우려 사항을 설명합니다.


“Unsanitized input from the HTTP request body flows into child_process.exec, where it is used to build a shell command. This may result in a Command Injection vulnerability.”


그러나 해당 url 매개 변수에서 안전하지 않은 exec () 함수로 데이터가 어떻게 흐를까요? 컨텍스트를 추가하려면 데이터 흐름의 보다 정교한 버전을 보려면 전체 세부 정보 버튼을 클릭하십시오.


Command injection vulnerability in Node.js 


여기에서 Snyk Code가 분석 한 방식으로 전체 그림을 명확하게 볼 수 있습니다.


url 매개 변수는 변수 req.body.content에 메시지 본문 입력으로 흐르는 사용자 제어 입력의 소스 인 항목 배열에서 생성됩니다.


명령 주입 수정 


이제 다음과 같은 보안 문제를 해결하기 위해 추가 조치를 취할 수 있습니다.


  • 안전하지 않은 exec()를 사용하는 대신 해당 API의 안전한 버전 인 execFile()을 사용할 수 있습니다.이 API는 배열 함수 인수의 형태로 제공된 인수를 이스케이프 처리합니다.
  • 항목 변수가 시스템 프로세스 실행과 같은 민감한 코드로 흘러 들어가기 전에 사용자 입력에서 항목 변수를 검증, 이스케이프 또는 삭제해야 합니다.

요약 


여기까지 따라 오 셨다면 잘하셨습니다!


이제 코드 삽입 취약점으로 인해 발생할 수 있는 문제에 대해 더 잘 알고 있기를 바랍니다. 자체 코드에서 생성되었는지 또는 애플리케이션에서 가져온 타사 종속성에서 생성되었는지 여부.


이 게시물이 유용하다고 생각되면 Snyk의 동료들이 제공하는 후속 읽기 자료가 있습니다.



댓글목록 0

등록된 댓글이 없습니다.

웹학교 로고

온라인 코딩학교

코리아뉴스 2001 - , All right reserved.