Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
StealMyBitcoin-PoC — Публичный релиз задачи Steal My Bitcoin | Kitploit
Инструменты/GitHubGitHub/killaboi/stealmybitcoin-poc
Криминалистика памятиАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийCTFРазработка Полезной НагрузкиЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHubkillaboi/stealmybitcoin-poc

StealMyBitcoin-PoC

Публичный релиз задачи Steal My Bitcoin

Репозиторий
21641601 день назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

спонсировано с ❤️ от hextree.io

Proof of concept для CTF Steal My Bitcoin

Один живой PHP-колбэк против задачи Steal My Bitcoin, от начала до конца, в одном файле Python со стандартной библиотекой.

Python Dependencies Target Lab

Этот README описывает stealmybitcoin_poc.py — однофайловое воспроизведение на Python последовательности запросов, использованной в моём прохождении CTF Steal My Bitcoin. Используется только стандартная библиотека Python. Скрипт сам формирует запросы, проверяет каждую утечку перед переходом к следующему шагу и записывает HTTP-байты нового запуска.

Вероятно, это можно сделать проще, без всей лишней отладочной мишуры, и, как я обнаружил в своём видео про John Hammond о повышении привилегий в Steam Local, этот уродливый PoC наверняка можно причесать.

[!NOTE] ⚠️ Честно говоря, пожалуйста, причешите его или сделайте свою лучшую версию, не скомканную Sol. ⚠️

Всё ниже написано для Docker-лаборатории, а не для живого челленджа. Лаборатория — это локальный Alpine PHP 8.4.26 CLI-сервер за nginx, та же сборка и та же модель воркеров, на которых калибровались смещения. Поднимите её за минуту, и вся цепочка пройдёт от начала до конца на вашей машине. Живой запуск, который действительно решил задачу, сохранён как историческая заметка внизу.

  stage                 what goes out                        what comes back
  ─────────────────────────────────────────────────────────────────────────────
  0  health      GET /php-version.php                 ->  PHP 8.4.26 confirmed
  1  heap leak   249,042 B producer + 8 x   6,672 B   ->  256 B cookie
                 (OOM poisons a worker)                   └─ Zend chunk base
  2  code leak   251,557 B producer + 8 x  92,388 B   ->   16 B cookie
                 (OOM poisons a worker)                   └─ zval_ptr_dtor
  3  callback    368,812 B POST                       ->  forged HashTable runs
                 (fake HashTable + command)               └─ zif_system(cmd)
  ─────────────────────────────────────────────────────────────────────────────
  20 HTTP requests at most. No looping, no retries.

Краткая версия

  1. Небольшая multipart-загрузка заставляет PHP потреблять гораздо больше памяти, чем предполагает размер передаваемых данных.
  2. Когда память заканчивается посреди разбора прогресса загрузки сессии, PHP оставляет устаревшее состояние в воркере, который затем используется повторно.
  3. Правильно сформируйте последующие запросы, и байты утекут через cookie сессии. Я читаю их как адрес кучи и адрес кода PHP.
  4. Имея оба адреса, финальный запрос помещает поддельную структуру PHP туда, где её найдёт очистка, и очистка вызывает zif_system — обработчик PHP для system.
  5. Эта команда отправляет обратно свежий маркер-доказательство и один результат print-flag по всё ещё открытому соединению.

Почему два адреса? ОС рандомизирует расположение кода и кучи PHP независимо. Утечка кучи сообщает скрипту, куда поместить поддельную структуру, а утечка кода сообщает, где на самом деле находится функция, которую он хочет вызвать. Адреса из более раннего воркера или более раннего запуска не являются безопасной заменой, и каждый раз, когда я пробовал это, попытка просто проваливалась.

Содержание

  • Лаборатория
  • Начните здесь
  • Что делает каждый запрос
    • 1. Как небольшой производитель достигает лимита памяти
    • 2. Как восстанавливается адрес кучи
    • 3. Как восстанавливается адрес кода PHP
    • 4. Как финальный запрос достигает system
  • Чтение результата
  • Как часто это на самом деле работает
  • Живой запуск, который это решил
  • Жаргон, кратко
  • Благодарности

Лаборатория

Смещения в этом PoC откалиброваны для Alpine PHP 8.4.26, запущенного со встроенным CLI-сервером с четырьмя воркерами. Лаборатория воспроизводит именно это, за nginx, на loopback.

[!IMPORTANT] Сборка важнее строки версии. Стек Debian php:8.4.26-fpm сообщает тот же PHP/8.4.26, но имеет другую компоновку бинарника, поэтому отпечаток указателя кода никогда не совпадёт, и запуск прервётся на этапе утечки кода. Используйте образ Alpine, приведённый ниже.

Три небольших файла. Поместите их в пустой каталог:

public/php-version.php (эндпоинт проверки работоспособности и единственная страница, которая нужна PoC)

<?php
header('Content-Type: text/plain');
echo 'PHP ', PHP_VERSION, "\n";
echo 'PID: ', getmypid(), "\n";

print-flag (заглушка для бинарника задания, должна быть исполняемой)

#!/bin/sh
printf '%s\n' 'LOCAL_DUMMY_WIF_NEVER_USE'

nginx.conf

events {}
http {
    server {
        listen 80;
        server_name _;
        location / {
            proxy_pass http://ctf-cross-php:8000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
        }
    }
}

Затем запустите его:

docker network create ctf-cross-net

docker run -d --name ctf-cross-php --network ctf-cross-net \
  --read-only --tmpfs /tmp:rw,size=32m,mode=1777 --memory 1g \
  -v "$PWD/public:/app:ro" \
  -v "$PWD/print-flag:/usr/local/bin/print-flag:ro" \
  -e PHP_CLI_SERVER_WORKERS=4 \
  php:8.4.26-fpm-alpine3.23 php -S 0.0.0.0:8000 -t /app

docker run -d --name ctf-cross-nginx --network ctf-cross-net \
  -p 127.0.0.1:18166:80 \
  -v "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" \
  nginx:1.27-alpine

Проверьте:

$ curl -s http://127.0.0.1:18166/php-version.php
PHP 8.4.26
PID: 1

PID зависит от того, какой воркер отвечает, и это нормально. Строка версии — это то, что проверяет PoC.

Удалите это с помощью docker rm -f ctf-cross-nginx ctf-cross-php && docker network rm ctf-cross-net.

[!TIP] В Windows запускайте эти команды docker run из PowerShell или замените $PWD на полный путь к диску, например C:/lab. В Git Bash $PWD разворачивается в путь MSYS, такой как /tmp/..., который Docker Desktop разрешает внутри своей собственной VM. Тогда bind-монтирования молча создают пустые каталоги там, где должны быть nginx.conf и print-flag, и контейнеры запускаются сломанными.

Несколько замечаний по этому рецепту. Образ — это тег fpm, но контейнер запускает php -S, поэтому SAPI — это cli-server, и именно относительно него проводилась калибровка. PHP_CLI_SERVER_WORKERS=4 — это то, что даёт этапам утечки более одного воркера для гонки. Мой собственный лабораторный стенд также передавал --cap-add SYS_PTRACE --security-opt seccomp=unconfined, чтобы можно было подключить трассировщик к воркерам; сам PoC этого никогда не делает, поэтому выше они опущены.


Начните здесь

Python 3.11 или новее, только стандартная библиотека, ничего устанавливать не нужно:

python .\stealmybitcoin_poc.py --url http://127.0.0.1:18166/php-version.php

Запустите его без аргументов — он выведет справку и завершится, не обращаясь к сети.

Успешный запуск выглядит так:

Скачать инструмент