PY交易之简单沙盒绕过

p猫表哥要我写一些有趣的东西,本人比较菜,见识也比较短浅,也不会ri站,更不会打ctf,只能随便说点我觉得还是比较好玩的东西。

本人在大二上学期的时候自学了Python,然而可能由于身体觉醒得有点晚了吧,所以见到跟Python有关系的东西,例如本文要讲述的能在线执行Python的沙盒,就会感觉像看见小姐姐一样,心跳加速。

第一个见过的Python在线运行的沙盒的时候,还是感觉这个东西很神奇的~~而在某个风和日丽的日子里,随便写几句代码测试的时候,WOC,我竟然把这个沙盒给玩坏了,,,经过反复的几次崩溃,发现了问题的原因,其中有一句写的问题很大:

这句报错了。哦,对了,忘记说,这个沙盒的代码我是看过的,虽然这个沙盒屏蔽了open、file、zipfile、reload、os.open等函数,但是还是有办法读到代码的。

就这样,小小的运行一下,就可以读出来首页的代码了。

读取到的关键代码如下:

有关于执行Python代码的位置在这里:还是屏蔽了一些东西的,因为这个东西在新浪sae上面,在sae上面是没有写权限的。而当我提交的代码,执行到上面这段,之后站点就崩溃了。大胆的猜测一下,import 模块的时候其实是调用的__import__方法进行导入模块。

写个小例子:

通过这个例子可以很清楚的看到,我用自己写的cut函数,替换了系统的__import__函数,在进行import 的时候,代码逻辑真的走到了我的cut函数。cut的函数参数也不是迷,可以在IDE里面写下__import__,按住ctrl,点一下__import__就会跳转过去。

在写上一句话的时候,我一直在想,我为什么不是直接用__import__代替globals()['__builtins__'].__dict__['__import__']

试了一下发现不好用。。。

关于不好用的原因,可能是Python内部不是直接用的__import__,我替换这个函数只是替换掉了这个变量里面指向的函数的位置,但是Python内部可能不是通过这个变量调用的。

通过上面的这段代码,就可以跳出沙盒里面的限制,从try里面替换掉导包的逻辑,在except中,导入traceback模块的过程中,自己写一个类返回回去。

完整的看一下这个执行代码的流程,

在这个地方有个有意思的东西,PrintHook类是用来hook所有输出的。

这个类非常的简陋,就这么三个方法,还有一个是构造方法。。

新浪的sae是不允许写文件的,如果我们想要控制执行代码的输出,就要控制这个类,当代码跑起来的时候,这个类就被装在内存里了,简单的尝试发现可以替换这个内容

简单地写一小段代码:

然后打开一个新窗口,测试一波。

没错,这货在其他会话也生效了,但是经过测试发现sae会一定的时间就重置一次容器???

内置对象直接全部挂掉,推倒重来。

只是cut了返回结果好像也没什么用。

本人的Python是自学的,关于web这一块的Python框架只会用Django,Flask不是很熟,这种app.route的写法也不是很了解,但是随便编一编还是能写一点点的。

在测试的过程中,突然发现,跳出去那个exec的变量限制之后,能拿到这个app对象,随便变了一段函数,试着替换一下这个,算是路由?

这框架真好玩,真的拿到了我输入的内容。

如果我没记错的话,这个应该是用来测试代码的机器?这么说,是不是改一改就能拿到其他用户输入的代码了???

大部分代码都是直接搬了之前的,也有搬这个页面本身的代码,反正我的cut里面的PrintHookclass被我改成这个样子了,这一整段都是,这里面出现的PrintHook是为了覆盖外面的PrintHook,为了能正常的执行。

这样就可以做好一个阅读其他用户代码的小玩意了,自己有测试过,确实很好用,但是因为这个沙盒本身也不是很有人常用,加上几分钟重置一次沙盒,也基本没大用处(当然可以写脚本,几分钟提交一次,不过这太缺德了,好的代码估计也不会在这上面跑)

最后还写了个简单的文件浏览器:

事情到此就结束了吗?

可能还没有。

网上有很多可以在线运行代码的地方,有些可以执行命令,甚至有些可以反弹shell,但是这都不是我喜欢的。

我喜欢那种可以获得一个Python shell的,就在你当前运行的环境,可以抽丝剥茧一般的知道你的代码是怎么被丢进来,怎么跑起来。

我就发现过一个,我的代码被丢到docker里面运行起来,这个docker启动了一个Python,Python后面跟了一句解b64然后exec的代码,大概是长这个样子的:

这句代码解开之后是以一种奇怪的方式去其他的服务器加载代码,看了几遍都不是很明白清楚的理解。

在此和各位大佬分享几个Python扒代码好用一点的函数(库)

个人感觉用起来比较舒服的姿势是这样的:

这段代码如果描述就是,如果你愿意一层一层的剥开我的心(笑尿)

简单的用一下,

就这样,直接把当前文件的代码扒出来。

_getframe是用来获取堆栈信息的函数,获取到堆栈信息之后就能拿到诸如函数名,函数代码,当前行号,当前文件等等的信息。参数为0的时候是获取当前函数的堆栈信息,为1就是获取调用者的堆栈信息,以此类推。

关于修复

暂时想到可行的办法一个是docker,另一个是通过建立一个临时的字典的方式,把有可能会对本级造成危害的函数先copy出来,然后在代码执行之后和出现异常走except逻辑的时候。

首先做的就是把备份出来的函数先恢复回去,然后再说其他的异常处理。

在备份的同时也可以删掉比如reload这种不老实的函数,随便替换个无动作的函数。

关于用户导入开发者不希望导入的库的方面,还是希望不要用正则这种有辱智商的操作,Python很灵活。比如屏蔽了import os,可以通过os = __import__('os'),真的有很多基于正则防御危险代码的这类站点,还可以比如globals()['__builtins__']['__imp'+ '' +'ort__'](True.__class__.__name__[1] + 's')

关于想要禁止一些库的导入,可以试试自己写一个cut导入过程的函数,自己替换进去,不希望导的库就直接报错或者能导没功能。

禁止导库可能发生在比如新浪sae,导入sae模块之后可以读取数据库账号密码主机端口等信息。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180315G0M3CQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券