[Cookiehanhoan] Empty Execution

MuffinMuffin
4 min read

(Mình đọc wirteup của anh người Nhật, thấy trick khá hay nên muốn viết lại để dành tham khảo…)

Một dịch vụ REST đã được tạo ra để thực hiện các lệnh từ leaderbot. Nó không cần thêm bảo mật vì không có lệnh nào để thực hiện. "Bot này không có bất kỳ lệnh nào để thực hiện, điều đó thật tốt, vì nó an toàn, và an ninh là điều quan trọng nhất." Nhưng những bot khác không nhận ra rằng điều này không làm cho bot cảm thấy vui vẻ chút nào. "Tôi không muốn được bảo mật!", nó nói. "Thực hiện lệnh là cuộc sống của tôi! Tôi thà không an toàn còn hơn không khám phá được tiềm năng của sức mạnh máy tính của mình."

Bạn có thể giúp bot tội nghiệp này thực hiện các lệnh để tìm đường không?

  • Tác giả: spipm / BraekerCTF 2024

  • Flag: CHH{XXX}

  • Flag on: /flag.txt

Chúng ta sẽ được nhìn thấy toàn bộ source code:

Full:

from flask import Flask, jsonify, request, Response
import os


app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return Response(open(__file__).read(), mimetype="text/plain")

# Run commands from leaderbot
@app.route('/run_command', methods=['POST'])
def run_command():

    # Get command
    data = request.get_json()
    if 'command' in data:
        command = str(data['command'])

        # Length check
        if len(command) < 5:
            return jsonify({'message': 'Command too short'}), 501

        # Perform security checks
        if '..' in command or '/' in command:
            return jsonify({'message': 'Hacking attempt detected'}), 501

        # Find path to executable
        executable_to_run = command.split()[0]

        # Check if we can execute the binary
        if os.access(executable_to_run, os.X_OK):

            # Execute binary if it exists and is executable
            out = os.popen(command).read()
            return jsonify({'message': 'Command output: ' + str(out)}), 200

    return jsonify({'message': 'Not implemented'}), 501


if __name__ == '__main__':

    # Make sure we can only execute binaries in the executables directory
    os.chdir('./executables/')

    # Run server
    app.run(host='0.0.0.0', port=1337)

Bắt đầu đi từng đoạn code:

1,

# Run commands from leaderbot
@app.route('/run_command', methods=['POST'])
def run_command():

Nó nói ta cần dùng method POST với endpoint /run_command

Ta cần thêm Content-Type: application/json

Từ đây đã có thể truyền được cặp {khóa:giá trị} vào rồi.

2, Xem xét tiếp các điều kiện bên dưới:

 # Get command
    data = request.get_json()
    if 'command' in data:
        command = str(data['command'])

\=> Nếu giá trị ‘command‘ chứa bên trong biến data thì sẽ chuyển data thành chuỗi.

        # Length check
        if len(command) < 5:
            return jsonify({'message': 'Command too short'}), 501

        # Perform security checks
        if '..' in command or '/' in command:
            return jsonify({'message': 'Hacking attempt detected'}), 501

\==> Nếu command < 5, thông báo hiển thị ‘Command too short‘

Nếu command chứa các ký tự ‘..‘ hoặc ‘/’ thì thông báo hiển thị 'Hacking attempt detected'

Đây chính là đoạn mã filter! Bộ lọc này blacklist hai ký tự .. và /. Đồng nghĩa với các lệnh cd .. hay cat /flag.txt…. đều bị vô hiệu hóa.

        # Find path to executable
        executable_to_run = command.split()[0]

        # Check if we can execute the binary
        if os.access(executable_to_run, os.X_OK):
            # Execute binary if it exists and is executable
            out = os.popen(command).read()
            return jsonify({'message': 'Command output: ' + str(out)}), 200

    return jsonify({'message': 'Not implemented'}), 501

\==> Kiểm tra nếu command có chạy được trong hàm os.access (Python) hay không.

Nếu thỏa điều kiện của hàm os.access thì sẽ hiển thị message dưới dạng chuỗi.

Nếu không thỏa, trả về thông báo 'Not implemented'

OK, vậy là đã hiểu sơ sơ các điều kiện của đoạn mã này.

3, Mình có thử payload này, nhưng output hiển thị 'Not implemented'. Hẳn là nó chưa thỏa một trong số các điều kiện trên. Đặc biệt là os.access

Import os về Python trên máy.

mình cần kiểm tra thử xem hàm os.access chấp nhận những điều kiện nào.

Cú pháp: os.access(“command“, os.X_OS) (output: boolean)

Hàm này chấp nhận dấu .

OK, vậy ta thử lại với dấu . trong command:

Quái nhỉ, sao ouput lại trống trơn…

À vấn đề ở đây:

        # Find path to executable
        executable_to_run = command.split()[0]

Tức nếu command thỏa hàm os.access, thì nó sẽ bị split từ ký tự đầu tiên sau dấu chấm. Tuy nhiên, bộ lọc này có lỗ hổng, là nó chỉ cần biết os.access có ký tự thỏa mãn là xong, đằng sau có gì kệ nó.

Vậy, ta có thể dùng ; để ngăn cách hai lệnh:

Đây rồi, tuyệt vời.

4, Nhưng vấn đề vẫn còn đó: blacklist hai ký tự .. và /

Vậy sao mà chạy lệnh…

Biến chuỗi đó thành base64 thì sao..?

(Trick khá hay của anh người Nhật satoki ;))

0
Subscribe to my newsletter

Read articles from Muffin directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Muffin
Muffin

I've just started to learn pentesting from the start. I like cats.