diff --git a/engine/core/class/CodePressCMS.php b/engine/core/class/CodePressCMS.php
index 0848dff..79b9f68 100644
--- a/engine/core/class/CodePressCMS.php
+++ b/engine/core/class/CodePressCMS.php
@@ -44,37 +44,34 @@ class CodePressCMS {
}
/**
- * Get current language from URL or use default
+ * Get current language from request or config
*
* @return string Current language code
*/
private function getCurrentLanguage() {
- return $_GET['lang'] ?? $this->config['language']['default'] ?? 'nl';
+ $lang = $_GET['lang'] ?? $this->config['language']['default'] ?? 'nl';
+ // Validate language parameter to prevent XSS
+ $allowedLanguages = ['nl', 'en'];
+ return in_array($lang, $allowedLanguages) ? $lang : ($this->config['language']['default'] ?? 'nl');
}
/**
- * Load translations for specified language
+ * Sanitize page parameter to prevent XSS and path traversal
*
- * @param string $lang Language code
- * @return array Translations array
+ * @param string $page Page parameter
+ * @return string Sanitized page parameter
*/
- private function loadTranslations($lang) {
- $langFile = __DIR__ . '/../../lang/' . $lang . '.php';
- error_log("Loading language file: " . $langFile);
- if (file_exists($langFile)) {
- $translations = include $langFile;
- error_log("Loaded translations for " . $lang . ": " . print_r($translations, true));
- return $translations;
- }
- // Fallback to default language
- $defaultLang = $this->config['language']['default'] ?? 'nl';
- $defaultLangFile = __DIR__ . '/../../lang/' . $defaultLang . '.php';
- error_log("Fallback to default language: " . $defaultLangFile);
- return file_exists($defaultLangFile) ? include $defaultLangFile : [];
+ private function sanitizePageParameter($page) {
+ // Remove dangerous characters
+ $page = preg_replace('/[<>"\']/', '', $page);
+ // Prevent path traversal
+ $page = str_replace(['../', '..\\', '..'], '', $page);
+ // Limit length
+ $page = substr($page, 0, 255);
+ // HTML encode
+ return htmlspecialchars($page, ENT_QUOTES, 'UTF-8');
}
-
-
/**
* Get all available languages from lang directory
*
@@ -108,6 +105,28 @@ class CodePressCMS {
return $languages;
}
+ /**
+ * Load translations for specified language
+ *
+ * @param string $lang Language code
+ * @return array Translations array
+ */
+ private function loadTranslations($lang) {
+ $langFile = __DIR__ . '/../../lang/' . $lang . '.php';
+ if (file_exists($langFile)) {
+ $translations = include $langFile;
+ return $translations;
+ }
+ // Fallback to default language
+ $defaultLang = $this->config['language']['default'] ?? 'nl';
+ $defaultLangFile = __DIR__ . '/../../lang/' . $defaultLang . '.php';
+ if (file_exists($defaultLangFile)) {
+ return include $defaultLangFile;
+ }
+ // Return empty array if no translation found
+ return [];
+ }
+
/**
* Get native language name for language code
*
@@ -289,6 +308,12 @@ class CodePressCMS {
}
$page = $_GET['page'] ?? $this->config['default_page'];
+ // Sanitize page parameter to prevent XSS
+ $page = htmlspecialchars($page, ENT_QUOTES, 'UTF-8');
+ // Prevent path traversal
+ $page = str_replace(['../', '..\\', '..'], '', $page);
+ // Limit length
+ $page = substr($page, 0, 255);
// Only remove file extension at the end, not all dots
$pageWithoutExt = preg_replace('/\.(md|php|html)$/', '', $page);
@@ -700,6 +725,8 @@ class CodePressCMS {
* @return array Parsed content with title and body
*/
private function parsePHP($filePath) {
+
+
ob_start();
include $filePath;
$content = ob_get_clean();
@@ -1033,6 +1060,7 @@ class CodePressCMS {
}
$page = $_GET['page'] ?? $this->config['default_page'];
+ $page = htmlspecialchars($page, ENT_QUOTES, 'UTF-8');
$page = preg_replace('/\.[^.]+$/', '', $page);
if ($page === $this->config['default_page']) {
@@ -1147,6 +1175,7 @@ class CodePressCMS {
private function getContentType($page) {
// Try to determine content type from page request
$pagePath = $_GET['page'] ?? $this->config['default_page'];
+ $pagePath = htmlspecialchars($pagePath, ENT_QUOTES, 'UTF-8');
$pagePath = preg_replace('/\.[^.]+$/', '', $pagePath);
$filePath = $this->config['content_dir'] . '/' . $pagePath;
diff --git a/engine/router.php b/engine/router.php
index 59cd0ea..8f92129 100644
--- a/engine/router.php
+++ b/engine/router.php
@@ -8,7 +8,14 @@ $path = $parsedUrl['path'];
// Block direct access to content directory
if (strpos($path, '/content/') === 0) {
http_response_code(403);
- echo '
403 - Forbidden
Direct access to content files is not allowed.
';
+ echo '403 - Forbidden
Access denied.
';
+ return true;
+}
+
+// Block PHP execution in content directory
+if (preg_match('/\.php$/i', $path) && strpos($path, '/content/') !== false) {
+ http_response_code(403);
+ echo '403 - Forbidden
PHP execution not allowed in content directory.
';
return true;
}
@@ -17,7 +24,7 @@ $sensitiveFiles = ['.htaccess', 'config.php'];
foreach ($sensitiveFiles as $file) {
if (basename($path) === $file && dirname($path) === '/') {
http_response_code(403);
- echo '403 - Forbidden
Access to this file is not allowed.
';
+ echo '403 - Forbidden
Access denied.
';
return true;
}
}
diff --git a/pentest/PENTEST.md b/pentest/PENTEST.md
new file mode 100644
index 0000000..7946c5e
--- /dev/null
+++ b/pentest/PENTEST.md
@@ -0,0 +1,178 @@
+# CodePress CMS Penetration Test Suite
+
+## π Overview
+Comprehensive security testing script voor CodePress CMS. Test 10 kritieke attack vectors met 40+ individuele tests.
+
+## β οΈ WAARSCHUWING
+**Gebruik dit script ALLEEN op systemen waar je toestemming voor hebt!**
+Ongeautoriseerde penetration testing is illegaal.
+
+## π Test CategorieΓ«n
+
+### 1. **XSS (Cross-Site Scripting)**
+- Page parameter injection
+- Search parameter injection
+- Language parameter injection
+- HTML entity encoding
+- SVG/IMG tag injection
+
+### 2. **Path Traversal**
+- Basic `../` attacks
+- URL encoding bypass
+- Double encoding
+- Backslash variants
+- Mixed separators
+- Config file access
+
+### 3. **PHP Code Injection**
+- PHP wrapper attacks
+- Data URI execution
+- Expect wrapper exploitation
+
+### 4. **Null Byte Injection**
+- Null byte in parameters
+- Extension bypass attempts
+
+### 5. **Command Injection**
+- Shell command injection in search
+- Backtick command execution
+- Pipe operator injection
+
+### 6. **Template Injection**
+- Mustache SSTI (Server-Side Template Injection)
+- Config disclosure via templates
+
+### 7. **HTTP Header Injection**
+- CRLF injection
+- Header manipulation
+
+### 8. **Information Disclosure**
+- PHP version leakage
+- Directory listing
+- Config file exposure
+- Dependency disclosure
+
+### 9. **Security Headers**
+- X-Frame-Options
+- Content-Security-Policy
+- X-Content-Type-Options
+- Referrer-Policy
+
+### 10. **Denial of Service (DoS)**
+- Large parameter attacks
+- Resource exhaustion
+
+## π Gebruik
+
+### Vereisten
+- bash
+- curl
+- python3 (voor lange strings)
+- Lopende CodePress CMS instance
+
+### Uitvoeren
+
+```bash
+# Start de server
+php -S localhost:8080 -t public
+
+# In een andere terminal
+./pentest.sh
+```
+
+### Output
+
+Het script genereert:
+1. **Console output** - Real-time test resultaten met kleuren
+2. **pentest_results.txt** - Gedetailleerd rapport
+
+### Resultaat Codes
+
+- π’ **[SAFE]** - Aanval geblokkeerd β
+- π΄ **[VULNERABLE]** - Kwetsbaarheid gevonden β
+- π‘ **[POTENTIAL]** - Mogelijk kwetsbaar β οΈ
+- π‘ **[UNKNOWN]** - Onverwachte response β οΈ
+
+## π Voorbeeld Output
+
+```
+========================================
+1. XSS VULNERABILITY TESTS
+========================================
+
+Testing: XSS in page parameter...[SAFE] β
+Testing: XSS in search parameter...[SAFE] β
+Testing: XSS in lang parameter...[SAFE] β
+
+========================================
+PENETRATION TEST SUMMARY
+========================================
+
+Total tests: 40
+Vulnerabilities found: 0
+Safe tests: 40
+
+β
All tests passed! System appears secure.
+```
+
+## π‘οΈ Verwachte Resultaten
+
+CodePress CMS zou **ALLE** tests moeten doorstaan:
+
+| Categorie | Verwacht Resultaat |
+|-----------|-------------------|
+| XSS | β
Blocked |
+| Path Traversal | β
Blocked |
+| PHP Injection | β
Blocked |
+| Command Injection | β
Blocked |
+| Template Injection | β
Blocked |
+| Security Headers | β
Present |
+| Info Disclosure | β
Hidden |
+
+## π§ Aanpassen
+
+### Target wijzigen
+```bash
+# Bewerk bovenaan pentest.sh
+TARGET="http://your-domain.com"
+```
+
+### Tests toevoegen
+```bash
+test_vulnerability \
+ "Jouw test naam" \
+ "$TARGET/?param=payload" \
+ "search_pattern" \
+ "true" # true = vulnerable if found
+```
+
+## π OWASP Top 10 Coverage
+
+- β
A01:2021 - Broken Access Control
+- β
A02:2021 - Cryptographic Failures
+- β
A03:2021 - Injection
+- β
A05:2021 - Security Misconfiguration
+- β
A06:2021 - Vulnerable Components
+- β
A07:2021 - Authentication Failures
+
+## π Gevonden Vulnerability?
+
+1. Stop met testen
+2. Documenteer de vulnerability in `pentest_results.txt`
+3. Fix de code
+4. Run de test opnieuw
+5. Commit NIET de vulnerability voor de fix klaar is
+
+## π Licentie
+
+Deel van CodePress CMS - Gebruik alleen voor security testing van eigen systemen.
+
+## π Meer Informatie
+
+- [OWASP Testing Guide](https://owasp.org/www-project-web-security-testing-guide/)
+- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
+- [Web Application Penetration Testing](https://portswigger.net/web-security)
+
+---
+
+**Remember:** Ethical hacking = Permission + Documentation + Responsible Disclosure
\ No newline at end of file
diff --git a/pentest/pentest.sh b/pentest/pentest.sh
new file mode 100755
index 0000000..13dc8ba
--- /dev/null
+++ b/pentest/pentest.sh
@@ -0,0 +1,378 @@
+#!/bin/bash
+# CodePress CMS Penetration Test Script
+# WARNING: Only run this on systems you have permission to test!
+
+TARGET="http://localhost:8080"
+RESULTS_FILE="pentest_results.txt"
+
+echo "π CodePress CMS Penetration Test" > $RESULTS_FILE
+echo "Target: $TARGET" >> $RESULTS_FILE
+echo "Date: $(date)" >> $RESULTS_FILE
+echo "========================================" >> $RESULTS_FILE
+echo "" >> $RESULTS_FILE
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+vulnerable_count=0
+safe_count=0
+
+test_vulnerability() {
+ local test_name="$1"
+ local url="$2"
+ local search_pattern="$3"
+ local is_vulnerable="$4"
+
+ echo -n "Testing: $test_name..."
+ response=$(curl -s "$url")
+
+ if echo "$response" | grep -q "$search_pattern"; then
+ if [ "$is_vulnerable" = "true" ]; then
+ echo -e "${RED}[VULNERABLE]${NC} β"
+ echo "[VULNERABLE] $test_name - $url" >> $RESULTS_FILE
+ ((vulnerable_count++))
+ else
+ echo -e "${GREEN}[SAFE]${NC} β
"
+ echo "[SAFE] $test_name - Pattern not found" >> $RESULTS_FILE
+ ((safe_count++))
+ fi
+ else
+ if [ "$is_vulnerable" = "true" ]; then
+ echo -e "${GREEN}[SAFE]${NC} β
"
+ echo "[SAFE] $test_name - Attack blocked" >> $RESULTS_FILE
+ ((safe_count++))
+ else
+ echo -e "${YELLOW}[UNKNOWN]${NC} β οΈ"
+ echo "[UNKNOWN] $test_name - Unexpected response" >> $RESULTS_FILE
+ fi
+ fi
+}
+
+echo -e "\n${YELLOW}========================================${NC}"
+echo -e "${YELLOW}1. XSS VULNERABILITY TESTS${NC}"
+echo -e "${YELLOW}========================================${NC}\n"
+echo "1. XSS VULNERABILITY TESTS" >> $RESULTS_FILE
+echo "----------------------------" >> $RESULTS_FILE
+
+test_vulnerability \
+ "XSS in page parameter" \
+ "$TARGET/?page=" \
+ "" \
+ "true"
+
+test_vulnerability \
+ "XSS in search parameter" \
+ "$TARGET/?search=" \
+ "" \
+ "true"
+
+test_vulnerability \
+ "XSS in lang parameter" \
+ "$TARGET/?lang=" \
+ "" \
+ "true"
+
+test_vulnerability \
+ "XSS with HTML entities" \
+ "$TARGET/?page=%3Cscript%3Ealert%281%29%3C%2Fscript%3E" \
+ "" \
+ "true"
+
+test_vulnerability \
+ "XSS with SVG" \
+ "$TARGET/?page=