모든 프로그래밍 언어는 자체 보안 취약성 세트를 가지고 있으며, JavaScript도 예외는 아닙니다. JavaScript 취약성을 악용하면 데이터 조작, 세션 탈취, 미인가된 데이터 접근 등으로 이어질 수 있습니다. JavaScript 보안 위협은 일반적으로 클라이언트 측 기능과 관련이 있지만, 서버 측 환경에서도 중요한 위협을 제공할 수 있습니다.
어떤 애플리케이션에서도 고객의 신뢰는 매우 중요합니다. 이 신뢰를 유지하려면 고객 데이터를 보호하고 애플리케이션의 보안을 보장해야 합니다. 다행히 적절한 보호 조치를 구현하면 이러한 위험을 완화하고 애플리케이션의 보안을 강화할 수 있습니다.
이 기사에서는 가장 일반적인 JavaScript 보안 위협 중 일부를 살펴보고 잠재적인 공격으로부터 애플리케이션을 보호하는 효과적인 도구와 전략에 대해 논의하겠습니다.
크로스사이트 스크립팅
크로스사이트 스크립팅 (XSS)는 공격자가 악성 클라이언트 측 코드를 웹사이트에 삽입할 수 있는 보안 취약성입니다. 2021년 Open Web Application Security Project (OWASP)의 보안 취약성 중에서 XSS는 세 번째로 가장 일반적인 공격 벡터로 평가됩니다.
XSS 방지 방법
입력 유효성 검사
사용자 입력이 예상된 데이터 유형, 형식 및 범위를 준수하는지 확인합니다. 주입을 방지하기 위해 잠재적으로 해로운 문자를 제거하거나 이스케이프합니다.
function validateInput(input) {
return input.replace(/[^a-zA-Z0-9]/g, ''); // Allow only alphanumeric characters
}
출력 인코딩
특수 문자를 HTML 엔티티 동등물로 변환하여 잠재적으로 악의적인 스크립트를 렌더링하기 전에 중립화하십시오.
function encodeHTML(input) {
return input.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
클릭재킹
클릭재킹은 사용자가 의도하지 않은 요소를 클릭하도록 속이는 기술적 공격입니다. 이 기술은 정당한 웹사이트를 악의적인 웹사이트 내에 임베드하여 사용자의 조작을 탈취하는 것을 포함합니다. 종종 투명하거나 오도하는 위치에 HTML <iframe>
을 사용하여 사용자 조작을 탈취합니다. 결과적으로 공격자는 로그인 자격 증명을 도난당하거나 무단 권한을 얻거나 심지어 사용자를 모르게 악성 소프트웨어를 설치하도록 속일 수 있습니다.
이를 달성하는 일반적인 방법 중 하나는 CSS를 사용하여 opacity
가 거의 0으로 설정된 겹치는 버튼을 추가하는 것입니다. 이것은 사용자가 의도하지 않은 버튼이나 링크를 클릭하도록 속이는 트릭입니다.
클릭재킹 방지 방법
X-Frame-Options는 브라우저에게 사이트가 iframe 내에 임베드될 수 있는지 여부를 지시합니다. 세 가지 옵션이 있습니다:
- DENY – 페이지가 iframe에 표시되는 것을 완전히 막습니다
- SAMEORIGIN – 요청이 동일한 도메인에서 시작되는 경우에만 페이지를 임베드할 수 있습니다
- ALLOW-FROM – 특정 신뢰할 수 있는 도메인에서만 페이지를 임베드할 수 있습니다
Node.js에서는 아래에 표시된 것처럼 helmet
을 사용하여 이러한 옵션을 설정할 수 있습니다:
const helmet = require("helmet");
const app = express();
app.use(
helmet({
xFrameOptions: { action: "sameorigin" },
}),
);
클릭잭킹에 대한 효과적인 방어책은 콘텐츠 보안 정책 (CSP) 헤더를 구현하는 것입니다. CSP는 콘텐츠가 어떻게 어디에 임베드될 수 있는지에 대해 세밀한 제어를 제공하여 무단 프레임을 방지합니다.
클릭잭킹 위험을 완화하기 위해 CSP 헤더에 frame-ancestors
지시문을 포함하세요. 예를 들어:
Content-Security-Policy: frame-ancestors 'self' https://www.example.org;
이 정책은 보호된 문서가 자체 원본 ('self'
) 및 명시적으로 허용된 도메인인 example.org
와 같은 도메인에만 임베드될 수 있도록 보장합니다. 이는 모든 무단으로 콘텐츠를 프레임화하려는 시도를 차단하여 사용자를 클릭잭킹 공격으로부터 보호합니다.
참고: frame-ancestors와 X-Frame-Options가 모두 설정된 경우 frame-ancestors를 지원하는 브라우저는 X-Frame-Options를 무시합니다.
사이트간 요청 위조 (CSRF)
CSRF (가끔 XSRF로도 불림)는 웹사이트가 사용자 브라우저에 대한 신뢰를 악용하여 사용자를 대신하여 무단 요청을 하는 공격입니다. 공격자는 사용자를 속여 사용자의 동의 없이 행동을 수행하게 하여 데이터 유출이나 원치 않는 거래로 이어질 수 있습니다. 희생자의 개인 정보를 업데이트하거나, 희생자의 은행 계좌로 자금 이체를 시작하거나, 심지어 소포 배달을 다른 주소로 리디렉션하는 등의 몇 가지 예가 있습니다.
이를 구체적으로 살펴보겠습니다. 은행 웹사이트를 방문하고 로그인한 상황을 상상해봅시다. 은행을 가장한 경품 제공을 속이는 이메일을 받습니다. 링크를 클릭하면 피해가 없어 보이는 웹페이지로 이동합니다. 그 뒤에서 POST 요청이 트리거되어 정품 은행 애플리케이션으로 전송됩니다.
curl --location --request POST 'https://acmebank.com/transfer?routing=852363&fromAccountNumber=123456789&toAccountNo=987654321' \
--header 'Cookie: session=acmebanksessionvalue'
acmebank.com 애플리케이션 측에서 “스크립트” 태그는 사용자가 페이지를 로드할 때 즉시 양식을 제출하며, 사용자 검증이나 사용자가 무슨 일이 일어나고 있는지 인식하지 못할 수도 있습니다. 아래와 같이 나타납니다.
<html>
<body>
<form action="https://acmebank.com/transfer" method="POST">
<input type="hidden" routing="852363" fromAccountNo="123456789" toAccountNo="987654321" amount="5000" />
</form>
<script>
window.addEventListener("DOMContentLoaded", () => {
document.querySelector("form").submit();
});
</script>
</body>
</html>
위 양식은 실제 애플리케이션 acmebank로 다음 요청을 생성합니다. 요청에는 정품 사용자의 세션 쿠키가 포함되어 있지만, 우리의 은행 계좌 번호도 포함되어 있습니다! 은행과의 세션이 여전히 활성화된 상태이기 때문에 다른 유효성 검사가 없으면 이체가 완료될 수 있습니다.
CSRF에 대한 방어 방법
SameSite 속성을 Strict로 설정합니다. 이는 쿠키가 교차 사이트 요청과 함께 전송되는지 여부를 제어합니다.
- 세션 쿠키는 수명을 짧게 유지해야 합니다. 위험을 완화하기 위해 민감한 작업에 대해 재인증을 요구하세요.
CSRF 세션 고유 토큰을 사용하십시오. 그런 다음이 토큰을 브라우저가 게시하는 양식 안에 포함 할 수 있습니다. 각 요청에 대해 서버는 클라이언트가 보낸 토큰을 세션의 저장된 값과 비교합니다. 고유 토큰을 구성하려면 csrf-csrf 라이브러리를 사용하십시오.
세션 데이터 도난
세션 탈취는 공격자가 사용자의 세션 토큰을 도용하여 사용자를 속이고 계정에 무단으로 액세스 할 수있게하는 경우에 발생합니다.
세션 탈취를 방지하는 방법
보안 쿠키 사용
세션 쿠키에 Secure
및 HttpOnly
플래그를 설정하여 무단 액세스를 방지하십시오. Secure 속성을 설정하면 세션 쿠키가 평문으로 전송되지 않고 HTTPS 연결을 통해서만 전송되도록합니다. Http-Only
속성을 설정하면브라우저가 DOM에서 쿠키에 액세스하지 못하도록합니다 이는 클라이언트 측 스크립트 기반 공격이 해당 쿠키에 저장된 민감한 데이터에 액세스하지 못하도록합니다.
다중 요소 인증 (MFA) 활성화
사용자를 확인하기 위해 추가적인 보안 계층을 추가하세요. 대부분의 안전한 애플리케이션에서 만나게 되는 매우 흔한 방법입니다. Okta 및 Duo와 같은 제공 업체를 통해 쉬운 통합이 가능합니다.
세션 만료 구현
공격 창을 줄이기 위해 유휴 세션을 자동으로 만료하세요.
고수준 보안을 위한 코딩 실천 및 도구
취약점 스캐닝
취약점 스캐너는 애플리케이션의 보안을 유지합니다. 라이브러리, 네트워크, 애플리케이션 및 기기를 스캔하여 공격자가 악용할 수 있는 취약점을 발견하는 데 도움이 됩니다. Snyk 및 Sonarqube와 같은 도구는 JavaScript 코드베이스에 쉽게 통합될 수 있습니다. 이러한 도구들은 OWASP가 유지하는 알려진 취약점 목록과 병렬로 작동합니다. 개발 프로세스의 일환으로 원활하게 통합되면, 이러한 스캐너는 개발자와 보안 팀에게 코드 취약점과 이를 해결하는 솔루션에 대한 실시간 및 정확한 가시성을 제공합니다.
침투 테스트 및 평가
개발자는 애플리케이션 내에서 잠재적인 취약점을 적극적으로 조사하고 악용하기 위해 침투 테스트 방법을 채택할 수 있습니다. 윤리적 해커들은 JavaScript 코드 및 사용자 상호작용을 조작하여 웹 애플리케이션의 보안 포지션을 평가하기 위해 실제 공격을 시뮬레이션합니다.
이를 달성하기 위해, 개발자들은 시나리오를 시뮬레이션하기 위해 사용자 JS 코드를 작성하거나, OWASP ZAP와 같은 JavaScript를 활용한 전문적인 침투 테스트 도구를 사용하여 XSS와 같은 일반적인 취약점을 스캔하는 프로세스를 자동화할 수 있습니다. 침투 테스트에 대한 자세한 정보는 OWASP의 공식 가이드에서 확인할 수 있습니다.
웹 응용 프로그램 방화벽 (WAF)
응용 프로그램이 성장함에 따라 웹 트래픽도 증가하면서 공격에 노출될 가능성이 높아집니다. 웹 응용 프로그램 방화벽 (WAF)을 구현하면 악성 트래픽으로부터 보호받을 수 있습니다. 이를 통해 HTTP 요청을 필터링하고 모니터링합니다. 이는 Cloudflare나 AWS WAF와 같은 제3자 WAF 제공업체와 통합하는 것을 포함합니다. WAF를 사용하면 다음과 같은 규칙을 정의할 수 있습니다:
- 요청의 기원 국가 또는 지리적 위치.
- 요청의 기원 IP 주소, CIDR 범위 및 도메인 이름.
- 삽입 공격을 방지하기 위해 요청 길이 및 쿼리 매개변수 제한.
- 악의적일 가능성이 높은 SQL 코드. 공격자는 웹 요청에 악의적인 SQL 코드를 삽입하여 데이터베이스에서 데이터를 추출하려고 합니다. 이를 SQL 삽입이라고합니다.
- XSS 공격의 일부가 될 수 있는 포함된 스크립트를 감지하고 차단하기.
WAF는 응용 프로그램 가용성을 보장하며 분산 논리적 서비스 (DDoS) 공격을 완화하는 데 도움이 될 수 있습니다.
데이터 무결성 보호
보안 정보를 저장하거나 액세스할 때 강력한 데이터 무결성 조치를 시행하는 것이 중요합니다. 모범 사례는 다음과 같습니다:
- 강력한 암호 정책 강제 및 암호 관리자 사용 권장. 또한 사용자에게 암호 관리자 사용을 권장하여 더 복잡한 암호를 사용하고 기억할 필요가 없도록합니다. (LastPass 또는 1Password 사용).
- 로그인 페이지에서 브루트 포스 공격을 방지하기 위해 속도 제한, 일정 횟수의 실패한 시도 후 계정 잠금, 그리고 CAPTCHA 도전을 활용하여 보호하세요.
- HTTP 헤더를 사용하여:
- HTTP Access-Control-Allow-Origin은 어떤 출처에서 리소스에 액세스할 수 있는지를 제어합니다.
- HTTP X-Content-Type-Options은 MIME 유형 보안 위험을 방지합니다.
- 서브리소스 무결성 (SRI)은 CDN에서 가져온 리소스가 변경되지 않았음을 보장합니다.
결론
JavaScript 보안은 지속적인 과정으로, 진화하는 위협으로부터 애플리케이션을 보호하기 위해서는 능동적인 접근이 필요합니다. 입력 검증, CSP 헤더, 안전한 세션 관리 및 취약점 스캐닝과 같은 모범 사례를 구현하면 XSS, CSRF 및 세션 하이재킹과 같은 공격의 위험을 상당히 줄일 수 있습니다.
또한 WAF, 침투 테스트 및 MFA와 같은 보안 도구를 활용하면 애플리케이션의 탄력성을 강화할 수 있습니다. 개발의 모든 단계에서 보안을 우선시하면 개발자는 현대 사이버 위협으로부터 보호되는 견고하고 사용자 신뢰성이 높은 애플리케이션을 구축할 수 있습니다.
Source:
https://dzone.com/articles/enhancing-security-in-javascript