通过Ajax提交JSON后PHP的$GLOBALS配置被意外修改的问题
Hey there, let's dig into your problem and figure out why your $GLOBALS config is getting modified, plus how to fix it for good.
Your setup uses json_decode(file_get_contents("php://input"), true) to grab the Ajax-sent JSON, but if you're doing any of the following with that input array, you're opening the door to variable overwrites:
- Using
extract($postData)to turn JSON keys into global variables - Merging the input array directly into
$GLOBALS(likearray_merge($GLOBALS, $postData)) - Assigning input values to
$GLOBALSwithout explicit checks
For example, if an attacker sends a malicious JSON payload like this:
{"email_id": "attacker@example.com", "password": "hunter2", "user": "malicious_user", "password": "hacked_pass"}
And your code uses extract() on the decoded array, it will directly overwrite your $GLOBALS['user'] and $GLOBALS['password'] values. That's exactly what's happening here.
Stop using unsafe methods that map user input to global variables. Instead, explicitly extract only the fields you need:
// Safely receive and process the Ajax request $rawInput = file_get_contents("php://input"); $postData = json_decode($rawInput, true); // Only pull the fields you actually use, with fallback defaults $email = filter_var($postData['email_id'] ?? '', FILTER_VALIDATE_EMAIL); $password = $postData['password'] ?? ''; // Now use only $email and $password for your login logic—no touchy with $GLOBALS!
This way, any extra keys in the attacker's payload get ignored, and your global config stays intact.
If you're not sure where the overwrite is happening, add debug logs to track $GLOBALS values at key points:
// At the end of config.php error_log("Post-config load: DB User = " . $GLOBALS['user'] . ", DB Pass = " . $GLOBALS['password']); // At the start of your login handler script error_log("Login script start: DB User = " . $GLOBALS['user']); // Right after processing the input data error_log("After input processing: DB User = " . $GLOBALS['user']);
Check your server's error log (usually in /var/log/apache2/error.log or similar) to see exactly when the values change. That will point you straight to the problematic code.
Storing database credentials in $GLOBALS is risky because global variables are mutable. A far safer approach is to use constants, which can't be modified after they're defined:
// In config.php, replace $GLOBALS assignments with constants define('DB_USER', $configuration['database']['username']); define('DB_PASS', $configuration['database']['password']); define('DB_NAME', $configuration['database']['database']); define('DB_HOST', $configuration['database']['host']); // When connecting to the database, use the constants $dbConnection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
Even if there's a variable overwrite issue elsewhere, constants will stay untouched.
While you're fixing this, add these layers to make your login system more robust:
- Add CSRF protection: Generate a unique token on the login page, include it in the Ajax request, and validate it on the backend to prevent cross-site request forgery.
- Hash passwords properly: Never store plain-text passwords. Use
password_hash()when creating user accounts, andpassword_verify()during login. - Rate limit login attempts: Block repeated failed login requests from the same IP to stop brute-force attacks.
内容的提问来源于stack exchange,提问作者Onkar

