Hack The Box Templated 문제를 풀어봅시다.
Description
Can you exploit this simple mistake?
Solve
문제 웹 사이트에 접근하면 다음과 같다. Flask
로 만들어진 웹 페이지를 확인할 수 있다.
URL에 test 입력시 test라는 문구가 출력된다.
SSTI
공격이 가능할 것으로 추측되어 $
를 입력 해보니 49가 출력이 된다.
쉘을 실행시키기 위해 subprocess.Popen
찾았다. 인덱스는 414
이다.
이다음 cat flag.txt
를 하여 플래그를 획득할 수있다.
How is RCE possible?
python에서 모든 객체는 `` 속성을 가집니다.
1
2
3
#<class 'str'>
__mro__
를 통해 자신과 자신이 상속받은 클래스, 상속받은 클래스의 상위 클래스까지 순서대로 튜플 타입으로 반환합니다. __base__
를 통해 object 클래스에 접근할수도 있습니다.
1
2
#(<class 'str'>, <class 'object'>) #우리는 object 타입을 이용할 것이므로 [1]인덱스를 필요로합니다.
__subclasses__
는상속을 받는 클래스가 어떻게 구성이 되어 있는지를 나타냅니다. 엄청나게 많은 클래스들이 나오며 우리가 필요한 클래스 인덱스를 찾아 사용이 가능합니다.
1
2
#[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>....
414 인덱스에는 subprocess.Popen
이 됩니다. subprocess.Popen
을 사용하는 이유는subprocess.Popen
을 이용하여 쉘 명령을 실행할 수 있습니다. subprocess를 보면 os.system
모듈과 기능을 대체한다고 되어있습니다.
1
2
{ ''.__class__.__mro__[1].__subclasses__()[414] }}
#<class 'subprocess.Popen'>
Popen을 보시면 Popen의 생성자를 알 수 있습니다.
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None)¶
args
에는 id
라는 명령이 들어가며, shell=True
를 통해 쉘을 호출합니다. subclasses.Popen는 기본적으로 Shell=False
로 지정되기 때문에 shell=True
를 통해 쉘을 호출해야합니다.
그리고stdout=-1
을 통해 표준출력을 지정합니다. -1은 subprocess.PIPE
을 의미합니다. subprocess.PIPE = -1인 이유 마지막으로 communicate()
에서 stdout에서 데이터를 읽어옵니다.
1
Reference
https://me2nuk.com/SSTI-Vulnerability/ https://watchout31337.tistory.com/177 https://stackoverflow.com/questions/71547832/popen-stdout-value