balderdashy / balderdashy/sails
Invalid body in fake POST API calls potential security vulnerability
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 22.8k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
**Node version**: 14
**Sails version** _(sails)_: 1.4.4 and 1.5.0
**ORM hook version** _(sails-hook-orm)_: 4.0.0
**Sockets hook version** _(sails-hook-sockets)_: 2.0.1
**Organics hook version** _(sails-hook-organics)_: n/a
**Grunt hook version** _(sails-hook-grunt)_: n/a - not using
**Uploads hook version** _(sails-hook-uploads)_: n/a - not using
**DB adapter & version** _(e.g. sails-mysql@5.55.5)_: na - not using
**Skipper adapter & version** _(e.g. skipper-s3@5.55.5)_: 0.9.1
Make API Call with fake body data:
`POST /api/fake/call`
Body (use application\json):
`{ Fake broken data}`
This should return a 404 because the API is not listed in routes.js. But instead some of the underlying code (body-parser, skipper) is being called before an error occurs and it returns the full API stack back to the calling API.
This was discovered because of actual attempts that were trying out the following code on a site I have log access to. I confirmed that partial execution containing malicious executable code was *attempted* but the following error was spit back, most likely preventing the execution. The containers were recycled anyway for safety.
`
381
2021-12-15T17:59:36.389-08:00
2021-12-16T01:59:36.389Z [32minfo[39m: <<<< POST /data6688/open/getCompanyInfo (time: 10) :: [code: 400]
382
2021-12-15T17:59:36.382-08:00
2021-12-16T01:59:36.382Z [31merror[39m: Unable to parse HTTP body- error occurred :: 'UnsupportedMediaTypeError: unsupported charset "UTF8"\n' +
383
2021-12-15T17:59:36.382-08:00
' at jsonParser (**redacted**/node_modules/skipper/node_modules/body-parser/lib/types/json.js:126:12)\n' +
384
2021-12-15T17:59:36.382-08:00
' at _parseHTTPBody (**redacted**/node_modules/skipper/lib/skipper.js:119:5)\n' +
385
2021-12-15T17:59:36.382-08:00
' at Layer.handle [as handle_request] (**redacted**/node_modules/express/lib/router/layer.js:95:5)\n' +
386
2021-12-15T17:59:36.382-08:00
' at trim_prefix (**redacted**/node_modules/express/lib/router/index.js:317:13)\n' +
387
2021-12-15T17:59:36.382-08:00
' at **redacted**/node_modules/express/lib/router/index.js:284:7\n' +
388
2021-12-15T17:59:36.382-08:00
' at Function.process_params (**redacted**/node_modules/express/lib/router/index.js:335:12)\n' +
389
2021-12-15T17:59:36.382-08:00
' at next (**redacted**/node_modules/express/lib/router/index.js:275:10)\n' +
390
2021-12-15T17:59:36.382-08:00
' at cookieParser (**redacted**/node_modules/cookie-parser/index.js:57:14)\n' +
391
2021-12-15T17:59:36.382-08:00
' at Layer.handle [as handle_request] (**redacted**/node_modules/express/lib/router/layer.js:95:5)\n' +
392
2021-12-15T17:59:36.382-08:00
' at trim_prefix (**redacted**/node_modules/express/lib/router/index.js:317:13)\n' +
393
2021-12-15T17:59:36.382-08:00
' at **redacted**/node_modules/express/lib/router/index.js:284:7\n' +
394
2021-12-15T17:59:36.382-08:00
' at Function.process_params (**redacted**/node_modules/express/lib/router/index.js:335:12)\n' +
395
2021-12-15T17:59:36.382-08:00
' at next (**redacted**/node_modules/express/lib/router/index.js:275:10)\n' +
396
2021-12-15T17:59:36.382-08:00
' at responseTimeLogger (**redacted**/config/http.js:61:18)\n' +
397
2021-12-15T17:59:36.382-08:00
' at Layer.handle [as handle_request] (**redacted**/node_modules/express/lib/router/layer.js:95:5)\n' +
398
2021-12-15T17:59:36.382-08:00
' at trim_prefix (**redacted**/node_modules/express/lib/router/index.js:317:13)\n' +
399
2021-12-15T17:59:36.382-08:00
' at **redacted**/node_modules/express/lib/router/index.js:284:7\n' +
400
2021-12-15T17:59:36.382-08:00
' at Function.process_params (**redacted**/node_modules/express/lib/router/index.js:335:12)\n' +
401
2021-12-15T17:59:36.382-08:00
' at next (**redacted**/node_modules/express/lib/router/index.js:275:10)\n' +
402
2021-12-15T17:59:36.382-08:00
' at requestLogger (**redacted**/config/http.js:68:20)\n' +
403
2021-12-15T17:59:36.382-08:00
' at Layer.handle [as handle_request] (**redacted**/node_modules/express/lib/router/layer.js:95:5)\n' +
404
2021-12-15T17:59:36.382-08:00
' at trim_prefix (**redacted**/node_modules/express/lib/router/index.js:317:13)'
405
2021-12-15T17:59:36.379-08:00
2021-12-16T01:59:36.379Z [32minfo[39m: >>>> POST /data6688/open/getCompanyInfo
`
The above should have returned a 404 and never processed ANY code outside of validation of the route. The various librraries involved are a concern if the malicious code contained cookies or file uploads. It may not have executed anything but it should not have informed the hacker that this was a valid url with some kind of server.
This should have generated a 404 and without error stack information.
I'm also able to reproduce this easily on my end as well and it returns the error stack back to the API caller which is no bueno either.
At worst this is a serious security issue. At best, the API should return a 404 without any callstack information.
I've also installed a vanilla version of Sails 1.5.0 WebApp and can reproduce the same issue.
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
Reproduce the invalid POST against the vanilla Sails 1.5.0 app, then trace route handling through routes.js and the body-parser/skipper middleware shown in the report. Review the Express stack and the middleware references in config/http.js. Done means an unlisted route returns 404 without processing the body or exposing an error stack.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- express, javascript, node.js
- Domain
- api, backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100