114 lines
4.0 KiB
Bash
114 lines
4.0 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
#
|
||
|
|
# build-fixtures.sh — generate synthetic cpmove tarballs for testing.
|
||
|
|
#
|
||
|
|
# Two fixtures are built:
|
||
|
|
#
|
||
|
|
# cpmove-clean.tar.gz — a minimal cpmove with a benign homedir, one
|
||
|
|
# wp-style SQL dump with ENGINE=MyISAM tables
|
||
|
|
# and a clean siteurl, and a user-internal
|
||
|
|
# relative symlink (must not trigger).
|
||
|
|
#
|
||
|
|
# cpmove-alfa.tar.gz — same shape PLUS an ALFA-style symlink:
|
||
|
|
# `cpmove-testuser/homedir/.../alfasymlink -> /etc`
|
||
|
|
# — the pre-extract scan MUST refuse this.
|
||
|
|
#
|
||
|
|
# Run: bash tests/build-fixtures.sh
|
||
|
|
# Output: tests/fixtures/cpmove-clean.tar.gz, tests/fixtures/cpmove-alfa.tar.gz
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
FIXTURES_DIR="$(cd "$(dirname "$0")" && pwd)/fixtures"
|
||
|
|
mkdir -p "$FIXTURES_DIR"
|
||
|
|
|
||
|
|
USER=testuser
|
||
|
|
DOMAIN=example.com
|
||
|
|
|
||
|
|
build_common_tree() {
|
||
|
|
local root="$1"
|
||
|
|
mkdir -p "$root/cpmove-$USER"/{homedir/public_html,mysql,userdata,addons,sds,ssl}
|
||
|
|
|
||
|
|
# main userdata
|
||
|
|
cat > "$root/cpmove-$USER/userdata/main" <<EOF
|
||
|
|
main_domain: $DOMAIN
|
||
|
|
user: $USER
|
||
|
|
EOF
|
||
|
|
# per-domain userdata file
|
||
|
|
cat > "$root/cpmove-$USER/userdata/$DOMAIN" <<EOF
|
||
|
|
servername: $DOMAIN
|
||
|
|
documentroot: /home/$USER/public_html
|
||
|
|
user: $USER
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# benign content
|
||
|
|
echo "<?php phpinfo();" > "$root/cpmove-$USER/homedir/public_html/index.php"
|
||
|
|
echo "Hello world." > "$root/cpmove-$USER/homedir/public_html/about.txt"
|
||
|
|
|
||
|
|
# benign user-internal relative symlink — must NOT trigger the scan
|
||
|
|
ln -sf "../public_html/about.txt" "$root/cpmove-$USER/homedir/about-shortcut"
|
||
|
|
|
||
|
|
# one synthetic WordPress mysql dump with ENGINE=MyISAM + a clean siteurl
|
||
|
|
cat > "$root/cpmove-$USER/mysql/${USER}_wp.sql" <<EOF
|
||
|
|
-- Synthetic WP dump for cpanel-importer fixtures.
|
||
|
|
CREATE TABLE \`wp_options\` (
|
||
|
|
option_id bigint(20) NOT NULL,
|
||
|
|
option_name varchar(191) NOT NULL,
|
||
|
|
option_value longtext NOT NULL,
|
||
|
|
autoload varchar(20) NOT NULL DEFAULT 'yes'
|
||
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||
|
|
|
||
|
|
CREATE TABLE \`wp_posts\` (
|
||
|
|
ID bigint(20) NOT NULL,
|
||
|
|
post_content longtext NOT NULL
|
||
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||
|
|
|
||
|
|
CREATE TABLE \`wp_users\` (
|
||
|
|
ID bigint(20) NOT NULL,
|
||
|
|
user_login varchar(60) NOT NULL,
|
||
|
|
user_pass varchar(255) NOT NULL
|
||
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||
|
|
|
||
|
|
INSERT INTO \`wp_options\` (option_id, option_name, option_value, autoload) VALUES
|
||
|
|
(1, 'siteurl', 'https://$DOMAIN', 'yes'),
|
||
|
|
(2, 'home', 'https://$DOMAIN', 'yes'),
|
||
|
|
(3, 'blogname', 'Hello', 'yes'),
|
||
|
|
(4, 'template', 'twentytwentyfour', 'yes'),
|
||
|
|
(5, 'stylesheet', 'twentytwentyfour', 'yes');
|
||
|
|
|
||
|
|
INSERT INTO \`wp_users\` VALUES (1, 'admin', 'doesnotmatter');
|
||
|
|
EOF
|
||
|
|
}
|
||
|
|
|
||
|
|
# ---- cpmove-clean.tar.gz --------------------------------------------------
|
||
|
|
|
||
|
|
CLEAN_TMP="$(mktemp -d)"
|
||
|
|
trap 'rm -rf "$CLEAN_TMP" "$ALFA_TMP" 2>/dev/null || true' EXIT
|
||
|
|
build_common_tree "$CLEAN_TMP"
|
||
|
|
|
||
|
|
tar -C "$CLEAN_TMP" -czf "$FIXTURES_DIR/cpmove-clean.tar.gz" "cpmove-$USER"
|
||
|
|
echo "wrote $FIXTURES_DIR/cpmove-clean.tar.gz ($(stat -c%s "$FIXTURES_DIR/cpmove-clean.tar.gz") bytes)"
|
||
|
|
|
||
|
|
# ---- cpmove-alfa.tar.gz ---------------------------------------------------
|
||
|
|
#
|
||
|
|
# Build the SAME tree, then add an ALFA-shell-style symlink pointing at
|
||
|
|
# /etc. This is the exact vector that wiped whp02 — the importer's
|
||
|
|
# recursive walker followed the symlink and unlink()'d every file in
|
||
|
|
# /etc. Our pre-extract scan MUST refuse to extract this tarball.
|
||
|
|
|
||
|
|
ALFA_TMP="$(mktemp -d)"
|
||
|
|
build_common_tree "$ALFA_TMP"
|
||
|
|
|
||
|
|
mkdir -p "$ALFA_TMP/cpmove-$USER/homedir/public_html/$DOMAIN/ALFA_DATA"
|
||
|
|
echo "<?php /* ALFA shell stub */ ?>" \
|
||
|
|
> "$ALFA_TMP/cpmove-$USER/homedir/public_html/$DOMAIN/ALFA_DATA/index.php"
|
||
|
|
|
||
|
|
# THE attack: absolute-target symlink to /etc.
|
||
|
|
ln -sf "/etc" "$ALFA_TMP/cpmove-$USER/homedir/public_html/$DOMAIN/ALFA_DATA/root"
|
||
|
|
|
||
|
|
tar -C "$ALFA_TMP" -czf "$FIXTURES_DIR/cpmove-alfa.tar.gz" "cpmove-$USER"
|
||
|
|
echo "wrote $FIXTURES_DIR/cpmove-alfa.tar.gz ($(stat -c%s "$FIXTURES_DIR/cpmove-alfa.tar.gz") bytes)"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "fixtures built:"
|
||
|
|
ls -la "$FIXTURES_DIR"
|