# Security Implications of Using Vanilla PHP and MySQL for a Game: Analysis of the PHPDTS Codebase

> Discover the security risks of vanilla PHP MySQL for games. Learn how PHPDTS fails to protect against SQL injection, XSS, and session hijacking.

- Repository: [Nemo Ma/phpdts](https://github.com/amarillonmc/phpdts)
- Tags: deep-dive
- Published: 2026-02-24

---

**Using vanilla PHP and MySQL for a multiplayer browser game eliminates framework-level security guardrails, requiring developers to manually implement every protection against SQL injection, XSS, and session hijacking—burdens that the PHPDTS repository currently fails to meet.**

The **amarillonmc/phpdts** repository implements a browser-based battle royale game using only core PHP and MySQL without modern frameworks, ORMs, or security libraries. This architectural choice keeps the codebase lightweight but shifts the entire security burden onto manual implementations. The following analysis examines critical vulnerabilities present in the source code, demonstrating how the absence of framework protections exposes the game to classical web application attacks.

## SQL Injection Vulnerabilities in login.php and user_profile.php

The most severe **security implication of using vanilla PHP** appears in the direct concatenation of user input into SQL strings. Without prepared statements or an ORM, the codebase constructs queries through string interpolation.

In [`login.php`](https://github.com/amarillonmc/phpdts/blob/main/login.php) at line 120, the authentication query concatenates the username directly:

```php
// login.php – line 120 (original)
$result = $db->query("SELECT * FROM {$gtablepre}users WHERE username = '$username'");

```

Similarly, [`user_profile.php`](https://github.com/amarillonmc/phpdts/blob/main/user_profile.php) at line 99 updates user records using raw string concatenation:

```php
// user_profile.php – line 99 (original)
$db->query("UPDATE {$gtablepre}users SET nick='$nick' … WHERE username='".$udata['username']."'");

```

**Secure alternative using prepared statements:**

```php
$stmt = $db->prepare("SELECT * FROM {$gtablepre}users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$result = $stmt->get_result();

```

This vulnerability allows attackers to bypass authentication or exfiltrate data by injecting malicious SQL through the username or nickname parameters.

## Cross-Site Scripting (XSS) Through Unescaped Game Logs

The game maintains a `$log` variable that concatenates player data and renders it in HTML without output encoding. In [`user_profile.php`](https://github.com/amarillonmc/phpdts/blob/main/user_profile.php) and various `*_func.php` files, user-controlled data like nicknames append directly to logs:

```php
// user_profile.php – line 26 (original)
$log .= "<b>{$udata['nick']}</b> updated their profile.<br>";

```

Because the code never applies `htmlspecialchars()`, an attacker could set a nickname containing `<script>` tags, executing arbitrary JavaScript in other players' browsers when the log renders.

**Secure output encoding:**

```php
$safeNick = htmlspecialchars($udata['nick'], ENT_QUOTES, 'UTF-8');
$log .= "<b>{$safeNick}</b> updated their profile.<br>";

```

## Cross-Site Request Forgery (CSRF) Exposure

State-changing operations in **vanilla PHP** require explicit CSRF token validation, which PHPDTS omits entirely. The registration and user management forms in [`register.php`](https://github.com/amarillonmc/phpdts/blob/main/register.php) (line 35) and [`user.php`](https://github.com/amarillonmc/phpdts/blob/main/user.php) (line 142) process POST requests without verifying anti-CSRF tokens. This allows attackers to forge requests that change passwords or transfer items if they can trick authenticated players into visiting malicious links.

## Session Hijacking and Fixation Risks

The session initialization in [`include/common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/include/common.inc.php) calls `session_start()` without configuring security flags. The default PHP session configuration lacks:
- `httponly`: Prevents JavaScript from accessing session cookies
- `secure`: Ensures cookies transmit only over HTTPS
- `sameSite`: Mitigates cross-site request attacks

Without these flags, attackers can steal session identifiers through XSS or intercept them over insecure connections.

## Insecure Direct Object References (IDOR)

The application exposes raw database identifiers in URLs (e.g., `?uid=123`) and uses them directly in queries without authorization checks. Multiple scripts execute `SELECT * FROM {$gtablepre}users WHERE uid='$uid'` without verifying whether the currently logged-in user owns that UID. This allows players to access or modify other users' profiles by manipulating URL parameters.

## File Inclusion and Path Traversal in game.php

Dynamic template loading in [`game.php`](https://github.com/amarillonmc/phpdts/blob/main/game.php) uses `include template('template_name');` where the template name derives from query parameters. Without a strict whitelist of allowable filenames, attackers could manipulate the parameter to include arbitrary files from the filesystem, executing unintended PHP code or exposing sensitive configuration data.

## Weak Password Cryptography

Rather than using one-way hashing, the authentication system in [`login.php`](https://github.com/amarillonmc/phpdts/blob/main/login.php) (line 137) stores passwords with reversible encryption:

```php
// login.php – line 137 (original)
$encrypted_pass = authcode($password, 'ENCODE', $key);

```

The `authcode()` function allows decryption of passwords, meaning a database breach exposes plaintext credentials. **Modern PHP security** requires `password_hash()` and `password_verify()` using bcrypt or Argon2:

```php
// Secure password handling
$hash = password_hash($password, PASSWORD_ARGON2ID);
// Verification
if (password_verify($password, $stored_hash)) { /* authenticated */ }

```

## Rate Limiting and Error Information Leakage

The login system in [`login.php`](https://github.com/amarillonmc/phpdts/blob/main/login.php) implements no brute-force protection, allowing unlimited authentication attempts. Additionally, [`install.php`](https://github.com/amarillonmc/phpdts/blob/main/install.php) outputs raw database errors directly to users via `gexit($db->error)`, revealing sensitive schema information, table prefixes, and server paths that aid attackers in crafting targeted exploits.

## Inconsistent Input Sanitization

While [`include/common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/include/common.inc.php) applies a custom `gstrfilter()` function to `$_REQUEST` at line 21, this blacklist approach proves insufficient and inconsistently applied. Many subsequent queries bypass the filter, and blacklist sanitization cannot anticipate all injection vectors.

## Summary

- **SQL injection** occurs throughout the codebase via direct query concatenation in [`login.php`](https://github.com/amarillonmc/phpdts/blob/main/login.php) and [`user_profile.php`](https://github.com/amarillonmc/phpdts/blob/main/user_profile.php), requiring immediate migration to prepared statements.
- **XSS vulnerabilities** stem from unescaped output in game logs and profile pages, necessitating `htmlspecialchars()` encoding on all user-generated content.
- **CSRF protection** is entirely absent from forms in [`register.php`](https://github.com/amarillonmc/phpdts/blob/main/register.php) and [`user.php`](https://github.com/amarillonmc/phpdts/blob/main/user.php), requiring token-based validation for all state-changing requests.
- **Session security** requires hardening `session_start()` calls in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) with `httponly`, `secure`, and `sameSite` cookie parameters.
- **Password storage** relies on reversible encryption via `authcode()` rather than one-way hashing, requiring replacement with `password_hash()`.
- **File inclusion** in [`game.php`](https://github.com/amarillonmc/phpdts/blob/main/game.php) needs strict whitelisting to prevent path traversal attacks.

## Frequently Asked Questions

### Is vanilla PHP secure enough for multiplayer browser games?

Vanilla PHP is capable of supporting secure multiplayer games only when developers manually implement all security controls that frameworks typically provide. The PHPDTS codebase demonstrates that without prepared statements, CSRF tokens, and output encoding, vanilla PHP creates significant attack surfaces for SQL injection, XSS, and session hijacking.

### Why does PHPDTS use reversible encryption for passwords instead of hashing?

The `authcode()` function in [`login.php`](https://github.com/amarillonmc/phpdts/blob/main/login.php) implements reversible encryption likely to support legacy authentication mechanisms or administrative password recovery features. However, this violates modern security standards by allowing plaintext password recovery if the encryption key is compromised. The repository should migrate to `password_hash()` with bcrypt or Argon2.

### Can attackers exploit the lack of CSRF tokens to cheat in the game?

Yes. Without CSRF tokens in forms located in [`user.php`](https://github.com/amarillonmc/phpdts/blob/main/user.php) and [`register.php`](https://github.com/amarillonmc/phpdts/blob/main/register.php), attackers can craft malicious websites that submit unauthorized requests on behalf of logged-in players. This could force unintended item transfers, profile modifications, or gameplay actions without the player's consent.

### How does the custom gstrfilter() function fail to protect against injection?

The `gstrfilter()` function in [`include/common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/include/common.inc.php) uses blacklist filtering that attempts to strip dangerous characters from `$_REQUEST`. This approach fails because blacklist sanitization cannot anticipate all SQL injection or XSS vectors, and many database queries in the codebase bypass the filter entirely, concatenating raw user input directly into SQL strings.