nextcloud / nextcloud/server

[Bug]: `Dispatcher` should parse and validate parameter types, fail if not as declared

Open
#46,289 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage 29-feedback bug technical debt
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

⚠️ This issue respects the following points: ⚠️
Bug description

Dispatcher should parse and validate parameter types, fail if not as declared

Expected

The dispatcher should fail calling the controller if the passed parameter type does not match the declared type.

Actual

The controller method is excuted with a wrong cast type.

Background

Coarse description of how requests are handled by controllers:

  1. Router finds matching route, finds controller class
  2. Dispatcher uses a reflector to inspect the target method arguments
  3. Dispatcher converts request parameters
  4. Dispatcher executes method on controller class
Analysis of executeController(Controller $controller, string $methodName)

The method extracts parameter values from the request and executes the looked up controller method with these parameters.

It uses a "Reflector" to determine types of the to-be-called method and tries to cast the types. It does not parse primitive values, but casts them.

Types can be specified by PHP comment annotation @type. Acceptable cast types are: int, integer, bool, boolean, float, double.

Type conversion is done via settype.

The problem

The problem with this is that wrong parameter values are silently converted to wrong values.

Passing a string notanumber to a controller method annotated with @int will result in a parameter 0 (type int) to be passed.

See also the example in the note below.

If zero is a valid value from the controller's point of view this might accidentally lead to a wrong code execution.

The proposed solution

The code shoud try to parse passed parameters and fail with an error response if parsing failed.

  • filter_var() alone is not suitable because it can't handle hex numbers
  • is_numeric() alone is not suitable because it can't handle hex numbers

I'm not familiar enough with PHP to come up with a thorough solution right now, but I think this involves testing the string using Regular Expressions, converting hex to decimal using hexdec() if applicable, combined with parsing them with filter_var().

Side note on settype()

The behavior of settype() is even unpredictable as it does not properly recognize (tempted to say "parse") the type. Here's an example with PHP 8.1.2:

php > $foo = "0x20";
php > settype($foo, "int");
php > echo $foo;
0
php > $foo = "20";
php > settype($foo, "int");
php > echo $foo
20
php > $bar = 0x20;
php > echo $bar;
32
Tried Github search terms:
  • is:issue controller type cast
  • is:issue controller type parameter

Tried Google searches:

  • nextcloud controller type parameter validate OR validation OR cast site:github.com
Steps to reproduce
  1. Find a controller that makes a method with @param int typed parameter callable via URL
  2. Call that route and pass a string
Expected behavior
  • The request fails
  • The controller method is not executed
Installation method

Community Manual installation with Archive

Nextcloud Server version

29

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.1

Web server

Apache (supported)

Database engine version

SQlite

Is this bug present after an update or on a fresh install?

Fresh Nextcloud Server install

Are you using the Nextcloud Server Encryption module?

None

What user-backends are you using?
  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other
Configuration report

No response

List of activated Apps

No response

Nextcloud Signing status

No response

Nextcloud Logs

No response

Additional info

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/private/AppFramework/Http/Dispatcher.php at executeController(), then reproduce the behavior with a controller method annotated with @param int and a nonnumeric URL value. Compare the existing settype-based conversion with the expected failure path. Done means invalid parameter values produce an error response and the controller method is not executed.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.