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 지원하기

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

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg

  1. 파라미터 이름에서 %00 이후의 모든 것을 무시합니다 .
  2. name[]를 배열로 처리합니다 .
  3. _GET가 GET Method를 의미하지 않습니다 .
  4. 마지막 파라미터를 우선합니다 .

Ruby 3.3.5 and WEBrick 1.8.2

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg

  1. &와 ; 구분자를 사용하여 파라미터를 분리합니다 .
  2. name[]를 인식하지 않습니다 .
  3. 첫 번째 파라미터를 우선합니다 .

Spring MVC 6.0.23 AND Apache Tomcat 10.1.30

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg

  1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping .
  2. POST RequestMapping & PostMapping이 name[]를 인식합니다 .
  3. name과 name[]가 모두 존재하는 경우 name을 우선합니다 .
  4. 파라미터를 연결합니다 (예: first,last) .
  5. POST RequestMapping & PostMapping은 Content-Type이 있는 query parameter를 인식합니다 .

NodeJS 20.17.0 AND Express 4.21.0

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg

  1. name[]를 인식합니다 .
  2. 파라미터를 연결합니다 (예: first,last) .

GO 1.22.7

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg

  1. name[]를 인식하지 않습니다 .
  2. 첫 번째 파라미터를 우선합니다 .

Python 3.12.6 AND Werkzeug 3.0.4 AND Flask 3.0.3

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg

  1. name[]를 인식하지 않습니다 .
  2. 첫 번째 파라미터를 우선합니다 .

Python 3.12.6 AND Django 4.2.15

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg

  1. name[]를 인식하지 않습니다 .
  2. 마지막 파라미터를 우선합니다 .

Python 3.12.6 AND Tornado 6.4.1

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg

  1. name[]를 인식하지 않습니다 .
  2. 마지막 파라미터를 우선합니다 .

JSON Injection

JSON, XML and YAML Hacking

중복 키

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 = 2
  • extra = ""

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

이는 불일치를 초래할 수 있습니다

참고 자료

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 지원하기