| name | security-audit |
| description | Security audit patterns for PHP/OWASP. Use when conducting security assessments, identifying vulnerabilities (XXE, SQL injection, XSS), or CVSS scoring. |
| metadata | {"version":"1.0.0"} |
Security Audit Skill
Security audits, vulnerability assessment, and secure coding patterns aligned with OWASP.
Expertise Areas
- Vulnerabilities: XXE, SQL injection, XSS, CSRF, auth flaws, insecure deserialization
- Risk Scoring: CVSS v3.1 methodology
- Secure Coding: Input validation, output encoding, cryptography, session management
OWASP Top 10 (2021)
| Rank | Category | Description |
|---|
| A01 | Broken Access Control | Unauthorized access to resources |
| A02 | Cryptographic Failures | Weak encryption, exposed secrets |
| A03 | Injection | SQL, NoSQL, OS, LDAP injection |
| A04 | Insecure Design | Missing security controls by design |
| A05 | Security Misconfiguration | Default configs, verbose errors |
| A06 | Vulnerable Components | Outdated libraries with CVEs |
| A07 | Auth Failures | Broken authentication/session |
| A08 | Data Integrity Failures | Insecure deserialization, CI/CD |
| A09 | Logging Failures | Missing audit logs, monitoring |
| A10 | SSRF | Server-side request forgery |
XXE Prevention
XML External Entity injection allows attackers to read files, perform SSRF, or DoS.
Vulnerable Code
$doc = new DOMDocument();
$doc->loadXML($userInput);
Secure Code
$doc = new DOMDocument();
$doc->loadXML(
$userInput,
LIBXML_NONET | LIBXML_NOENT | LIBXML_DTDLOAD
);
libxml_disable_entity_loader(true);
SimpleXML Secure Usage
$xml = simplexml_load_string(
$userInput,
'SimpleXMLElement',
LIBXML_NONET | LIBXML_NOENT
);
SQL Injection Prevention
Vulnerable Code
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
$result = $pdo->query($query);
Secure Code - PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
$result = $stmt->fetchAll();
Secure Code - TYPO3 QueryBuilder
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('users');
$result = $queryBuilder
->select('*')
->from('users')
->where(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->createNamedParameter($id, Connection::PARAM_INT)
)
)
->executeQuery()
->fetchAllAssociative();
XSS Prevention
Output Encoding
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_HTML5, 'UTF-8');
Fluid Templates
{variable}
{variable -> f:format.raw()}
{variable -> f:format.htmlspecialchars()}
Content Security Policy
header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';");
CSRF Protection
Form Tokens
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
throw new SecurityException('CSRF token mismatch');
}
TYPO3 CSRF Protection
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
$formProtection = $this->formProtectionFactory->createFromRequest($request);
$token = $formProtection->generateToken('myForm');
$isValid = $formProtection->validateToken($token, 'myForm');
API Key Encryption at Rest
Never store API keys in plain text. Use sodium for encryption:
<?php
declare(strict_types=1);
final class ApiKeyEncryption
{
public function encrypt(string $apiKey, string $key): string
{
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted = sodium_crypto_secretbox($apiKey, $nonce, $key);
return 'enc:' . base64_encode($nonce . $encrypted);
}
public function decrypt(string $encrypted, string $key): string
{
if (!str_starts_with($encrypted, 'enc:')) {
throw new \InvalidArgumentException('Invalid encrypted format');
}
$decoded = base64_decode(substr($encrypted, 4));
= (, , SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
= (, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
= (, , );
( === ) {
();
}
;
}
}
Password Hashing
Modern Password Hashing
$hash = password_hash($password, PASSWORD_ARGON2ID);
if (password_verify($inputPassword, $storedHash)) {
}
if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID)) {
$newHash = password_hash($password, PASSWORD_ARGON2ID);
}
TYPO3 Password Hashing
use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
$hashInstance = GeneralUtility::makeInstance(PasswordHashFactory::class)
->getDefaultHashInstance('BE');
$hash = $hashInstance->getHashedPassword($password);
$isValid = $hashInstance->checkPassword($password, $hash);
CVSS v3.1 Scoring
Base Metrics
| Metric | Values |
|---|
| Attack Vector (AV) | Network (N), Adjacent (A), Local (L), Physical (P) |
| Attack Complexity (AC) | Low (L), High (H) |
| Privileges Required (PR) | None (N), Low (L), High (H) |
| User Interaction (UI) | None (N), Required (R) |
| Scope (S) | Unchanged (U), Changed (C) |
| Confidentiality (C) | None (N), Low (L), High (H) |
| Integrity (I) | None (N), Low (L), High (H) |
| Availability (A) | None (N), Low (L), High (H) |
Severity Ratings
| Score | Severity |
|---|
| 0.0 | None |
| 0.1 - 3.9 | Low |
| 4.0 - 6.9 | Medium |
| 7.0 - 8.9 | High |
| 9.0 - 10.0 | Critical |
Example CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Score: 9.8 (Critical)
Translation:
- Network accessible
- Low complexity
- No privileges required
- No user interaction
- Unchanged scope
- High impact on C/I/A
Security Audit Checklist
Authentication & Authorization
Input Validation
Output Encoding
Secrets Management
Transport Security
Logging & Monitoring
Secure Configuration (TYPO3)
return [
'BE' => [
'debug' => false,
'lockIP' => 4,
'lockSSL' => true,
],
'FE' => [
'debug' => false,
'lockSSL' => true,
],
'SYS' => [
'displayErrors' => 0,
'devIPmask' => '',
'trustedHostsPattern' => 'example\\.com|www\\.example\\.com',
'features' => [
'security.backend.enforceReferrer' => true,
'security.frontend.enforceContentSecurityPolicy' => true,
],
],
];
Related Skills
Credits & Attribution
Thanks to Netresearch DTT GmbH for their contributions to the TYPO3 community.