티스토리 뷰

최종 수정: 2014-10-26


안녕하세요. Hackability 입니다.


오늘 포스팅 할 내용은 CSAW 2014 CTF에서 Pwn 200pt로 출제된 pybabbies에 대한 내용입니다.


문제 내용은 다음과 같습니다.

so secure it hurts


문제 소스 코드는 다음과 같습니다.


pyshell.py


파이썬 문제에서 보통 이런식으로 Sandbox 유형의 문제도 출제 되는 것 같습니다. 아직 뉴비를 벗어 나지 못한 저로써는 이런 문제도 처음엔 굉장히 당혹 스러웠습니다. :Q....


전체적으로 내용을 살펴보면, python 과 비슷한 행위를 하지만 특정 문자열이 오면 이를 막는 프로그램  입니다. 처음 부터 차근 차근 소스코드가 의미하는 바를 살펴 보도록 하겠습니다.


먼저, line 21 을 먼저 살펴 보도록 하겠습니다. 눈에 띄는 것은 __builtins__ 라는 모듈 입니다. 이 모듈은 이름 그대로 파이썬에 내장된 함수로써, 어떤 import 없이도 쓸 수 있는 함수를 갖고 있습니다. 어떤 내용을 갖고 있는지 살펴 보면 다음과 같습니다. (python 2.7.X)


[LINK]


우리가 기본적으로 파이썬에서 사용하는 함수들이 정의가 되어 있는 것을 볼 수 있습니다. print와 raw_input을 미리 빼줌으로써, print 함수와 raw_input 함수는 사용할 수 있을 것 같습니다. line 22 ~ 25에서는 Buill-in 함수를 모두 제거 하고 있습니다. 이로써, 문제에서는 파이썬에서 기본으로 제공되는 builtin 함수들을 사용하지 못하도록 막고 있습니다. 


line 27~36 에서는 사용자의 입력을 exec를 통해 실행하고 있습니다. 우리가 가장 하고 싶은 것은  print read('flag') 와 같은 역할을 하고 싶은데 banned 를 통해 유용한 키워드들이 모두 막혀 있습니다.


어디서 부터 시작을 해야 할지 막막해 하다가 Built-in 함수 중에 재미있는 함수가 하나 있습니다. 바로 dir()이라는 함수 입니다. dir 함수에 인자를 넣으면 해당 스코프에서 사용할 수 있는 이름을 반환합니다. 예를들어, 


dir_test.py

import sys

print dir(sys)


다음과 같이 sys에서 사용되는 가용한 attributes를 출력해 줍니다. 그렇다면 sandbox에서 의도치 않았지만 내장 함수 외 무언가 선언 없이 사용할 수 있는 것을 생각해보다가 banned 변수에서 리스트를 사용하고 있었기 때문에 리스트를 의미하는 [] 를 lookup 해보았습니다.


dir_test.py

import sys

print dir([])


오오... 뭔가 많은 속성을 갖고 있습니다. 이 중에 눈에 띄는 속성은 __class__ 입니다. 파이썬 도큐먼트에서는 다음과 같이 설명하고 있습니다. [new style class] 3.X 부터는 old style은 삭제 된다고 하네요. :0


위 도큐먼트의 설명에 있다 싶이, 2.2 이상의 파이썬에서는 new style의 class를 제공하 있는데 이는 몇 가지 특별한 함수를 내장 하고 있습니다. 이 중 관심이 있는 내장 객체로 __bases__ 라는 객체가 있습니다. 이는 메타 클래스 정보를 내장하고 있는 객체로 base 클래스에 대한 정보를 갖고 있습니다. 간단한 예를들면 다음과 같습니다.



위 파이썬 코드는 MyBase라는 클래스를 선언하고 A 클래스에서는 MyBase를 Base클래스로 갖는 클래스 입니다. 따라서, print_base를 하게 되면 __class__.__bases__를 통해 Base 클래스들에 접근을 하게 되고 __name__을 통해 base 클래스 들의 이름을 출력할 수 있게 됩니다.

(위의 예제에서는 MyBase 라는 문자열이 출력되게 됩니다.)


__bases__를 따라가게 되면, __subclasses__ 라는 함수가 있는데 이 함수는 서브 클래스의 모든 함수를 반환 해주는 함수 입니다. 다음과 같이 어떤 함수들이 있는지 살펴 보았습니다.


root@ubuntu:/media/psf/Home/ctf/2014_CSAW/pwn_200# python

Python 2.7.6 (default, Mar 22 2014, 22:59:56) 

[GCC 4.8.2] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> for k in [].__class__.__bases__[0].__subclasses__():

...     print k

... 

<type 'type'>

<type 'weakref'>

<type 'weakcallableproxy'>

<type 'weakproxy'>

<type 'int'>

<type 'basestring'>

<type 'bytearray'>

<type 'list'>

<type 'NoneType'>

<type 'NotImplementedType'>

<type 'traceback'>

<type 'super'>

<type 'xrange'>

<type 'dict'>

<type 'set'>

<type 'slice'>

<type 'staticmethod'>

<type 'complex'>

<type 'float'>

<type 'buffer'>

<type 'long'>

<type 'frozenset'>

<type 'property'>

<type 'memoryview'>

<type 'tuple'>

<type 'enumerate'>

<type 'reversed'>

<type 'code'>

<type 'frame'>

<type 'builtin_function_or_method'>

<type 'instancemethod'>

<type 'function'>

<type 'classobj'>

<type 'dictproxy'>

<type 'generator'>

<type 'getset_descriptor'>

<type 'wrapper_descriptor'>

<type 'instance'>

<type 'ellipsis'>

<type 'member_descriptor'>

<type 'file'>

<type 'PyCapsule'>

<type 'cell'>

<type 'callable-iterator'>

<type 'iterator'>

<type 'sys.long_info'>

<type 'sys.float_info'>

<type 'EncodingMap'>

<type 'fieldnameiterator'>

<type 'formatteriterator'>

<type 'sys.version_info'>

<type 'sys.flags'>

<type 'exceptions.BaseException'>

<type 'module'>

<type 'imp.NullImporter'>

<type 'zipimport.zipimporter'>

<type 'posix.stat_result'>

<type 'posix.statvfs_result'>

<class 'warnings.WarningMessage'>

<class 'warnings.catch_warnings'>

<class '_weakrefset._IterationGuard'>

<class '_weakrefset.WeakSet'>

<class '_abcoll.Hashable'>

<type 'classmethod'>

<class '_abcoll.Iterable'>

<class '_abcoll.Sized'>

<class '_abcoll.Container'>

<class '_abcoll.Callable'>

<class 'site._Printer'>

<class 'site._Helper'>

<type '_sre.SRE_Pattern'>

<type '_sre.SRE_Match'>

<type '_sre.SRE_Scanner'>

<class 'site.Quitter'>

<class 'codecs.IncrementalEncoder'>

<class 'codecs.IncrementalDecoder'>


다양한 함수들이 lookup이 되었습니다. 살펴 보면 41번째에 file이라는 함수가 있음을 알 수 있습니다. (WOW!!! 하고 싶다...) 그렇다면 이 녀석을 이용하여 flag를 읽어 보도록 하겠습니다.

 


이를통해 문제 파이썬 코드에서 의도치 않은 행위를 통해 flag 값을 읽을 수 있었습니다.

댓글
  • 프로필사진 ㅁㄴㅇ ㄷㄷ 저 주 수많은 것 중에서 어떻게 file임을 지목할 수 있죠 2017.09.14 02:34 신고
  • 프로필사진 hackability 저기서 하나를 선택한 이유는 저기서 타입 형태가 file이 존재 하기 때문에 선택을 했습니다. "<type 'file'>"

    만약 빌드인 내부에 모듈이 엄청 많고 그 내부에도 엄청많은데 딱 저 부분을 어떻게 선택햇는지 궁금하시다면 2가지 답변이 있습니다.

    1. 잘 알려진 위치

    파이썬에 저런식의 매직 가젯이 몇개 존재 합니다. 그 중에 [].__class__.__bases__[0].__subclasses__()[X] 는 가장 잘 알려진 가젯 중에 하나입니다. (X값은 버전 마다 다를 수 있습니다.)

    2. 모든 서브 키를 열거 하여 원하는 타입 찾기

    __builtins__ 클래스 내부를 for 문으로 조사하여 file 타입과 같이 관심 있는 타입을 찾으실수 있습니다.
    2017.09.14 12:57 신고
댓글쓰기 폼