EZ_command_injection

소스코드

app.py

  • 주어진 소스코드 중 중요파일은 “app.py” 파일입니다.
  • 사용자로부터 /ping?host={사용자 입력 값} 경로로 GET 요청을 전달받으면, 서버는 아래 코드를 순차적으로 실행합니다.
    • ipaddress.ip_address(host) 값이 유효한 값이라면 24라인에서 실행되는 OS 명령어의 인자로 사용되고
    • 유효하지 않은 값이라면 ValueError 예외 처리가 발생합니다.
  • 서버 측에 공격자가 원하는 운영체제 명령어를 실행시키기 위해서는 “host” 파라미터에 악성 페이로드를 삽입해야 하는데요. ipaddress.ip_address 함수가 받아들일 수 없는 값이 인자로 전달되는 경우 반드시 예외 처리(ValueError)가 발생하기 때문에 이를 우회할 수 있는 방안을 찾아야 합니다.

  • 먼저, 주어진 소스코드의 Dockerfile 에는 서버에서 사용중인 파이썬 버전(3.10)이 노출되고 있었습니다.

  • 파이썬 공식문서를 통해 파이썬 3.10 버전의 ipaddress 모듈 사용법을 확인해보았습니다.

  • ipaddress.ip_address(인자)는 인자로 전달된 IP 주소에 따라 IPv4/IPv6 객체를 반환한다고 합니다.

  • ipaddress.ip_address(address) 의 반환 값(IPv6 객체)에 대해 다시 IPv6(address)의 인자 값을 검증하는데요.

  • 이 때 인자 값을 %scope_id로 표시되는 스코프 존 ID를 설정하는게 가능했습니다.

    • (ipaddress.ip_address(address) 이 때부터 인자 값에 ScopeID를 설정할 수 있었던 것입니다.)

  • 위 정보를 토대로, 파이썬 3.10 버전에서 테스트를 진행해보겠습니다.
  • ipaddress.ip_address({사용자 입력 값}) 구조에서 사용자의 입력 값(host)을 아래와 같이 설정하면
  • 오류가 발생하지 않고 삽입된 문자열을 모두 정상적으로 인식하여 반환해주고 있습니다. (“ff02::5678%1;whoami”)
    • Baaaaam. 오류가 발생하지 않으니 공격자가 이 구간에 악성 페이로드를 삽입할 수 있겠죠?

  • 먼저, RCE 테스트를 위해 whoami 명령어를 실행해봤는데요. 대상 호스트의 계정정보(root)를 확인할 수 있었습니다.

  • 플래그는 앱 루트 디렉토리에 존재하므로 바로 출력해보면? 쨘! 하고 플래그가 출력됩니다. GG

번외

  • ipaddress.ip_address(host)에서 host 인자 값으로 “ff02::5678%1;whoami” 가 설정되었을 때 왜 오류가 발생하지 않는지 궁금했는데요.
  • 깃허브에서 Python 3.10 버전 ipaddress 모듈을 살펴 보니, 인자 값을 검증하는 로직이 아래와 같이 설정되어 있었습니다.
    • 1892 라인을 보면 ip_str.partition('%') 함수를 통해 % 문자를 기준으로 문자열을 나눠 튜플로 만들고 이 값을 각각 (addr, sep, scope_id) 에 할당하고 있었습니다. (따라서, % 뒤에 임의의 문자열(공격 페이로드)을 삽입해도 오류가 발생하지 않았던 것이죠.)

🐛.. 🐛.. 🐛..


REFERENCE

  1. https://docs.python.org/ko/3.10/library/ipaddress.html#ipaddress.IPv6Address
  2. https://learn.microsoft.com/en-us/previous-versions/aa921042(v=msdn.10)#scope-id
  3. https://compiliz.com/online-python-compiler
  4. https://github.com/python/cpython/blob/3.10/Lib/ipaddress.py