insane python


소스코드 분석

app.py, index.html

  • app.py 코드를 먼저 살펴보겠습니다. 플래그 정보는 전역변수로 선언된 CONFIG 딕셔너리에 저장되어 있습니다.
  • 웹 루트(/) 경로로 접근했을 때 body 파라미터로 받은 값은 io.StringIO(...) 함수의 인자로 사용되고
  • 이후 이 값은 sys.stdin.readline()에 의해 문자열로 읽혀 print_data(...) 함수의 인자로 다시 사용됩니다.
    • 그리고, print_data 함수의 리턴 값은 index.html 파일의 {{value}} 부분에 전달 및 출력됩니다.

  • 위 코드를 통해 CONFIG 딕셔너리에 정의된 SECRET 값을 어떻게 확인할 수 있는지 알아봐야 했는데요.
  • 파이썬 공식 문서로부터 function.__globals__ 속성에 대한 정보를 확인할 수 있었습니다.
    • function.__globals는 함수가 정의된 모듈 안의 전역 네임스페이스로, 함수의 전역 변수를 보관하는 사전에 대한 참조라고 합니다.
    • 즉, function.__globals__ 속성을 이용하면 동일 모듈 내에 선언된 전역 변수에 접근할 수 있는것이죠.

  • 테스트를 위해 주어진 소스코드와 유사한 환경을 재구성 해보았습니다.
  • DataConfig.__init__.__globals 를 출력해보면, app copy.py 내에 선언된 모든 전역변수 정보를 확인할 수 있습니다.

  • 위에서 확인한 정보를 토대로, 익스플로잇을 진행해보겠습니다.
  • print_data 함수는 아래와 같은 구조로 값을 리턴하고 있습니다.
    • format_string 인자는 사용자로부터 입력받은 값이고, config_dataDataConfig 클래스의 인스턴스 입니다.
    • 고렇다면, 인스턴스로 클래스의 함수를 호출하고, 함수의 전역변수로 접근해볼 수 있겠죠?
[ . . . ]
 
def print_data(format_string, config_data):
    return format_string.format(config_data=config_data)
    
[ . . . ]

  • 이렇게 말이죠. (DataConfig.__init__.__globals__ 혹은 DataConfig(...).__init__.__globals__)
  • 이제 GET 요청 시 body 파라미터에 넣어주면?! 쨘, 하고 플래그가 출력됩니다.

정리

동일한 파일에서 선언된 전역 변수라면 클래스 인스턴스로도 접근할 수 있다.
(클래스 인스턴스 → 메서드 → 메서드의 globals → 모듈 전역 dict → 동일 모듈 내 선언된 전역 변수 접근(읽기) 가능)

🐛.. 🐛.. 🐛..



REFERENCE

  1. https://stackoverflow.com/questions/71850147/where-does-a-compiled-function-get-its-globals?utm_source=chatgpt.com
  2. https://docs.python.org/3/reference/datamodel.html?utm_source=chatgpt.com#special-read-only-attributes