Parameter Pollution | JSON Injection
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HTTP Parameter Pollution (HPP) Overview
HTTP Parameter Pollution (HPP)는 공격자가 HTTP 파라미터를 조작하여 웹 애플리케이션의 동작을 의도치 않게 변경하는 기술입니다. 이 조작은 HTTP 파라미터를 추가, 수정 또는 중복시켜 이루어집니다. 이러한 조작의 효과는 사용자에게 직접적으로 보이지 않더라도 서버 측에서 애플리케이션의 기능을 크게 변경할 수 있으며, 클라이언트 측에서 관찰 가능한 영향을 초래할 수 있습니다.
Example of HTTP Parameter Pollution (HPP)
은행 애플리케이션의 거래 URL 예:
- 원본 URL:
https://www.victim.com/send/?from=accountA&to=accountB&amount=10000
추가적인 from 파라미터를 삽입하면:
- 조작된 URL:
https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC
거래가 accountA 대신 잘못하여 accountC로 청구될 수 있으며, 이는 HPP가 거래나 비밀번호 재설정, 2FA 설정, API key 요청 등과 같은 기능을 조작할 수 있음을 보여줍니다.
Technology-Specific Parameter Parsing
- 파라미터가 파싱되고 우선순위가 정해지는 방식은 기반 웹 기술에 따라 달라지며, 이는 HPP가 어떻게 악용될 수 있는지에 영향을 줍니다.
- Wappalyzer 같은 도구는 이러한 기술과 파싱 동작을 식별하는 데 도움을 줍니다.
PHP and HPP Exploitation
OTP 조작 사례:
- 상황: One-Time Password (OTP)를 요구하는 로그인 메커니즘이 악용되었습니다.
- 방법: Burp Suite 같은 도구로 OTP 요청을 가로채 HTTP 요청에서
email파라미터를 중복시켰습니다. - 결과: 원래 첫 번째 이메일로 전송되어야 할 OTP가 조작된 요청에 지정된 두 번째 이메일로 전송되었습니다. 이 결함으로 인해 의도된 보안 조치를 우회하여 무단 접근이 가능해졌습니다.
이 시나리오는 백엔드의 치명적인 실수를 보여주며, 백엔드는 OTP 생성에는 첫 번째 email 파라미터를 사용했지만 전송에는 마지막 값을 사용했습니다.
API Key 조작 사례:
- 상황: 애플리케이션이 프로필 설정 페이지를 통해 사용자가 API key를 업데이트할 수 있도록 허용했습니다.
- 공격 벡터: 공격자는 POST 요청에 추가
api_key파라미터를 덧붙이면 API key 업데이트 함수의 결과를 조작할 수 있음을 발견했습니다. - 기법: Burp Suite 같은 도구를 사용해 공격자는
api_key파라미터를 두 개 포함한 요청을 만듭니다: 하나는 정상, 다른 하나는 악의적입니다. 서버가 마지막 항목만 처리하면 API key가 공격자가 제공한 값으로 업데이트됩니다. - 결과: 공격자는 피해자의 API 기능을 장악하여 민감한 데이터를 무단으로 조회하거나 수정할 수 있습니다.
이 예는 특히 API key 관리처럼 중요한 기능에서 파라미터 처리를 안전하게 해야 할 필요성을 강조합니다.
Parameter Parsing: Flask vs. PHP
웹 기술이 중복된 HTTP 파라미터를 처리하는 방식은 다양하며, 이는 HPP 공격에 대한 취약성에 영향을 줍니다:
- Flask: 중복된 파라미터가 있을 때 처음 등장한 값을 채택합니다. 예: 쿼리 스트링
a=1&a=2에서는a=1을 우선시합니다. - PHP (on Apache HTTP Server): 반대로 마지막 파라미터 값을 우선시하여 예시에서는
a=2를 선택합니다. 이 동작은 공격자가 조작한 파라미터를 원본보다 우선시함으로써 의도치 않게 HPP 공격을 용이하게 할 수 있습니다.
HPP Testing Notes (OWASP WSTG)
- HTTP 표준은 동일한 이름의 여러 파라미터를 어떻게 해석해야 하는지를 정의하지 않으므로 스택과 구성 요소에 따라 동작이 달라집니다.
- 서버 측 HPP를 테스트할 때는 쿼리 문자열이나 본문에서 각 파라미터를 중복시키고 애플리케이션이 값을 연결하는지, 첫 번째/마지막 값을 사용하는지, 또는 에러를 발생시키는지 관찰합니다.
- 클라이언트 측 HPP의 경우 반영되는 파라미터 값에 URL 인코딩된
&(예:%26HPP_TEST)를 주입하고 생성된 링크나 form action 안에서 디코딩된&HPP_TEST또는&HPP_TEST와 같은 항목을 찾습니다.
Server-Side Parameter Pollution (SSPP) in Internal APIs
일부 애플리케이션은 사용자 입력을 내부 API로 보내는 서버 측 요청에 포함합니다. 해당 입력이 적절히 인코딩되지 않으면 내부 요청에서 파라미터를 주입하거나 덮어쓸 수 있습니다. 쿼리 파라미터, 폼 필드, 헤더, URL 경로 파라미터 등 모든 사용자 입력을 테스트하세요.
일반적인 프로브:
%26(URL 인코딩된&)로 새 파라미터를 추가합니다.%23(URL 인코딩된#)로 하위 쿼리를 잘라냅니다.- 파라미터를 중복시켜 기존 파라미터를 덮어씁니다.
Example:
GET /userSearch?name=peter%26name=carlos&back=/home
잠재적으로 다음과 같은 서버 측 요청을 발생시킬 수 있습니다:
GET /users/search?name=peter&name=carlos&publicProfile=true
Parameter pollution 기술별
결과는 https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89에서 가져왔습니다
PHP 8.3.11 AND Apache 2.4.62
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg
- 파라미터 이름에서 %00 이후의 모든 것을 무시합니다 .
- name[]를 배열로 처리합니다 .
- _GET가 GET Method를 의미하지 않습니다 .
- 마지막 파라미터를 우선합니다 .
Ruby 3.3.5 and WEBrick 1.8.2
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg
- &와 ; 구분자를 사용하여 파라미터를 분리합니다 .
- name[]를 인식하지 않습니다 .
- 첫 번째 파라미터를 우선합니다 .
Spring MVC 6.0.23 AND Apache Tomcat 10.1.30
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg
- POST RequestMapping == PostMapping & GET RequestMapping == GetMapping .
- POST RequestMapping & PostMapping이 name[]를 인식합니다 .
- name과 name[]가 모두 존재하는 경우 name을 우선합니다 .
- 파라미터를 연결합니다 (예: first,last) .
- POST RequestMapping & PostMapping은 Content-Type이 있는 query parameter를 인식합니다 .
NodeJS 20.17.0 AND Express 4.21.0
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg
- name[]를 인식합니다 .
- 파라미터를 연결합니다 (예: first,last) .
GO 1.22.7
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg
- name[]를 인식하지 않습니다 .
- 첫 번째 파라미터를 우선합니다 .
Python 3.12.6 AND Werkzeug 3.0.4 AND Flask 3.0.3
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg
- name[]를 인식하지 않습니다 .
- 첫 번째 파라미터를 우선합니다 .
Python 3.12.6 AND Django 4.2.15
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg
- name[]를 인식하지 않습니다 .
- 마지막 파라미터를 우선합니다 .
Python 3.12.6 AND Tornado 6.4.1
.png)
https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg
- name[]를 인식하지 않습니다 .
- 마지막 파라미터를 우선합니다 .
JSON Injection
중복 키
obj = {"test": "user", "test": "admin"}
front-end는 key의 첫 번째 발생을 신뢰할 수 있는 반면, backend는 두 번째 발생을 사용할 수 있다.
Key Collision: Character Truncation and Comments
일부 문자는 frontend에서 올바르게 해석되지 않지만 backend는 이를 해석하여 해당 keys를 사용한다. 이는 bypass certain restrictions에 유용할 수 있다:
{"test": 1, "test\[raw \x0d byte]": 2}
{"test": 1, "test\ud800": 2}
{"test": 1, "test"": 2}
{"test": 1, "te\st": 2}
이러한 경우 front end는 test == 1이라고 판단할 수 있고 backend는 test == 2라고 판단할 수 있다는 점에 유의하세요.
이 방법은 또한 다음과 같은 값 제한을 우회하는 데 사용될 수 있습니다:
{"role": "administrator\[raw \x0d byte]"}
{"role":"administrator\ud800"}
{"role": "administrator""}
{"role": "admini\strator"}
Comment Truncation 사용하기
obj = {"description": "Duplicate with comments", "test": 2, "extra": /*, "test": 1, "extra2": */}
여기서는 각 파서의 serializer를 사용하여 해당 출력을 확인합니다.
Serializer 1 (e.g., GoLang’s GoJay library) will produce:
description = "Duplicate with comments"test = 2extra = ""
Serializer 2 (e.g., Java’s JSON-iterator library) will produce:
description = "Duplicate with comments"extra = "/*"extra2 = "*/"test = 1
또는, 주석을 직접 사용하는 방식도 효과적일 수 있습니다:
obj = {"description": "Comment support", "test": 1, "extra": "a"/*, "test": 2, "extra2": "b"*/}
Java의 GSON 라이브러리:
{ "description": "Comment support", "test": 1, "extra": "a" }
Ruby의 simdjson 라이브러리:
{ "description": "Comment support", "test": 2, "extra": "a", "extra2": "b" }
우선순위 불일치: Deserialization vs. Serialization
obj = {"test": 1, "test": 2}
obj["test"] // 1
obj.toString() // {"test": 2}
Float and Integer
숫자
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
다음을 포함한 여러 표현으로 디코딩될 수 있습니다:
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9.999999999999999e95
1E+96
0
9223372036854775807
이는 불일치를 초래할 수 있습니다
참고 자료
-
https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654
-
https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution
-
https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89
-
https://bishopfox.com/blog/json-interoperability-vulnerabilities
-
https://portswigger.net/web-security/api-testing/server-side-parameter-pollution
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


