Lack of Anti-CSRF Protection in OpenWRT – /ubus Accepts Unauthorized Requests
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 7.9k
- Forks
- 2.9k
- Avg merge
- 4d 17h
- Merged PRs (30d)
- 28
Description
Is there an existing issue for this?
- I have searched among all existing issues (including closed issues)
screenshots or captures
Actual behaviour
During security testing with OWASP ZAP, an alert was triggered indicating Absence of Anti-CSRF Tokens in OpenWRT's /ubus API.
The issue was classified as Risk: Medium with Confidence: Low by OWASP ZAP.
Upon further manual verification, it was confirmed that no CSRF protection mechanism is enforced, allowing API calls to be executed with just a valid sessionid.
- In OpenWRT's JavaScript frontend (
L.env), bothsessionidandtokenare present. - However, the
tokenis never sent in any POST requests, meaning the API does not check for CSRF protection. - Requests to
/ubusare processed successfully as long as the attacker possesses thesessionid.
✅ Proof of Concept (PoC)
I successfully executed the following PowerShell script CSRF TEST:
$body = '[{"jsonrpc": "2.0", "id": 11, "method": "call", "params": ["SESSION_ID", "file", "write", {"path": "/etc/sysupgrade.conf", "data": "## CSRF TEST\n"}]}]'
Invoke-WebRequest -Uri "https://openwrt.home/ubus" `
-Method POST `
-Headers @{"Content-Type"="application/json"} `
-Body $body
🔹 Note: Replace SESSION_ID in the script above with the actual value of sessionid, which can be found in OpenWRT’s JavaScript frontend (L.env) or extracted from the sysauth_https session cookie in the browser.
As a result, the /etc/sysupgrade.conf file was modified, confirming that no CSRF validation occurs.
The tests were conducted both with and without an Nginx proxy, and the results remained the same.
Regardless of whether requests were sent directly to OpenWRT or proxied through Nginx, the API did not enforce CSRF protection.
If I misunderstood anything about the authentication or security model, please feel free to correct me. I appreciate any feedback!
Expected behaviour
- The
/ubusAPI should require a CSRF token to prevent unauthorized actions. - Requests without a valid CSRF token should be rejected with
Access Denied. sessionidshould not be enough to execute API requests without additional verification.
Steps to reproduce
1️⃣ Log into OpenWRT Web UI.
2️⃣ Open Developer Tools (F12) and locate sessionid using one of the following methods:
- Option 1: Elements Tab – Search for
sessionidinside the JavaScript objectL = new LuCI({...}). - Option 2: Console Tab – Enter the following command:
This will print theconsole.log(L.env);LuCIobject wheresessionidandtokenare defined.
3️⃣ Execute the PowerShell script above, replacing SESSION_ID with the extracted value.
4️⃣ The request succeeds, modifying the router’s configuration with ## CSRF TEST.
Additional Information
🔹 Tested on OpenWRT Versions:
OpenWrt 23.05.4 r24012-d8dd03c46f / LuCI openwrt-23.05 branch git-24.332.79522-a493155
OpenWrt 24.10.0 r28427-6df0e3d02a / LuCI openwrt-24.10 branch 25.014.55016~7046a1c
🔹 Backend Analysis:
The CSRF token is generated in dispatcher.uc by session_setup() using randomid(16).
However, it is never validated in /ubus requests, likely due to the test_post_security() function not being invoked.
🔹 Potential Impact:
If an attacker steals sessionid (via XSS, MITM, or session hijacking), they can execute arbitrary API requests.
Lack of CSRF validation allows full router compromise if sessionid is leaked.
What browsers do you see the problem on?
Firefox, Chrome, Microsoft Edge
Relevant log output
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading dispatcher.uc, especially session_setup() and the mentioned test_post_security() path, then trace how /ubus requests are handled alongside the LuCI frontend's sessionid and token. Reproduce the request on the listed OpenWrt versions and determine the intended validation boundary. Done means requests without a valid CSRF token are rejected while authenticated requests continue to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api, authentication, backend, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100