Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype access via action name (Security?) #9615

Open
bcaller opened this issue Apr 7, 2023 · 1 comment
Open

Prototype access via action name (Security?) #9615

bcaller opened this issue Apr 7, 2023 · 1 comment
Labels
bug Something isn't working p3-edge-case SvelteKit cannot be used in an uncommon way

Comments

@bcaller
Copy link

bcaller commented Apr 7, 2023

Describe the bug

In SvelteKit you can define actions for your page and invoke them with POST e.g. myAction can be hit at /myRoute?/myAction. However because of actions[name](event), you can also call any Object prototype properties such as:

__proto__, constructor, hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, toString, valueOf, __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__

For example, you can hit /myRoute?/isPrototypeOf, and this will call the equivalent of Object.prototype.isPrototypeOf.call(undefined, event) which will raise TypeError: Cannot convert undefined or null to object. The errors are because we are bound to undefined instead of an actual object.

The only one which doesn’t raise an error is toString which returns [object Undefined].

Hitting /myRoute?/constructor calls Object.prototype.constructor.call(undefined, event) which successfully returns event. The handler then tries to serialise event as a JSON response which would be a security issue, but event is not a POJO so it fails with an error like:

Error: Data returned from action inside /myRoute is not serializable: Cannot stringify a function (data..cookies.get)
    at try_deserialize (/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js:270:10)
    at stringify_action_response (/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js:252:9)
    at Module.handle_action_json_request (/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js:68:11)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

You can simply cause a 500 error in most SvelteKit applications by hitting one of these "actions".

I didn't report privately as a security vulnerability as I think this would only be dangerous if there were also some prototype pollution bug or an npm module installed which mutates the Object prototype with dangerous functions. In that case, any functions added to the prototype would be callable (though still with limited control of arguments) and this would be an awesome bug.

Reproduction

Using the example sverdle app:

curl 'http://localhost:5173/sverdle?/valueOf' -XPOST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost:5173'

curl 'http://localhost:5173/sverdle?/__proto__' -XPOST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost:5173'

curl 'http://localhost:5173/sverdle?/constructor' -XPOST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost:5173'

curl 'http://localhost:5173/sverdle?/toString' -XPOST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost:5173'

Logs

TypeError: Cannot convert undefined or null to object
    at isPrototypeOf (<anonymous>)
    at call_action (/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js:221:9)
    at Module.handle_action_json_request (/node_modules/@sveltejs/kit/src/runtime/server/page/actions.js:48:22)
    at Module.render_page (/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:43:9)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async resolve (/node_modules/@sveltejs/kit/src/runtime/server/respond.js:372:17)
    at async Module.respond (/node_modules/@sveltejs/kit/src/runtime/server/respond.js:243:20)
    at async /node_modules/@sveltejs/kit/src/exports/vite/dev/index.js:514:22

System Info

npmPackages:
    @sveltejs/adapter-auto: next => 2.0.0
    @sveltejs/kit: next => 1.15.2
    svelte: next => 3.58.0
    vite: ^4.2.0 => 4.2.1

Severity

annoyance

Additional Information

No response

@Conduitry Conduitry added bug Something isn't working p3-edge-case SvelteKit cannot be used in an uncommon way labels Feb 26, 2024
@Conduitry
Copy link
Member

Untested, but this could presumably be resolved by:

diff --git a/packages/kit/src/runtime/server/page/actions.js b/packages/kit/src/runtime/server/page/actions.js
index 64db81050..0c7fb1dfa 100644
--- a/packages/kit/src/runtime/server/page/actions.js
+++ b/packages/kit/src/runtime/server/page/actions.js
@@ -221,7 +221,7 @@ async function call_action(event, actions) {
 		}
 	}
 
-	const action = actions[name];
+	const action = Object.hasOwn(actions, name) && actions[name];
 	if (!action) {
 		throw new SvelteKitError(404, 'Not Found', `No action with name '${name}' found`);
 	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working p3-edge-case SvelteKit cannot be used in an uncommon way
Projects
None yet
Development

No branches or pull requests

2 participants