• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Prevent arbitrary URL parameters

#1
I know that there's a one-to-one relationship between the URL and the controller class/method as said in URI Routing. Also that any parameters that's passed to the URL (e.g. site/gate/login/foo, foo being the parameter), will be passed to the method (URI segments). Is there a way to prevent this?

If I have this gate/login controller, I do not want gate/login/foo to work. It should return 404. How do I force this? Do I need a manual check inside the login method? Do I need to set an explicit route? If so this doesn't seem to work, unless I'm missing some special syntax. How do I deal with this?

I'm using CI 3.1.11
Reply

#2
There are no setting to turn off the CI3 Routing. You can however comment out this line 423 in system\core\Router.php

PHP Code:
//$this->_set_request(array_values($this->uri->segments)); 

It will then only find manually defined routes in application\config\routes.php
Reply

#3
(05-09-2020, 07:22 AM)jreklund Wrote: There are no setting to turn off the CI3 Routing. You can however comment out this line 423 in system\core\Router.php

PHP Code:
//$this->_set_request(array_values($this->uri->segments)); 

It will then only find manually defined routes in application\config\routes.php

I don't really want to turn of routing. I'm already using it for some pages that don't map one-to-one. What I want to do is prevent adding arbitrary parameters to already working URL/controller.

I think this would be explained better with some concrete examples.

When I examine the CodeIgniter website repository, I see no custom route in route.php or a custom check in the index method of Download class. However, if I visit https://codeigniter.com/download/foo, I get a 404. https://codeigniter.com/download works just fine. The "foo" parameter doesn't get passed to the index method. If it were, I'd still be able to view the Download page even though the URL is https://codeigniter.com/download/foo.

Of course, this is assuming the site is still using the same code/repository. If not, why (and how) does https://codeigniter.com/download/foo return 404? And https://codeigniter.com/download works just fine? What prevents "foo" from being passed to the index method?

Using the freshly installed CodeIgniter, I simply want http://localhost/ci/index.php/welcome/index to work, but http://localhost/ci/index.php/welcome/index/foo to return 404.
Reply

#4
Hi, that project are not being used any more "This repository is no longer in effect, replaced by the CodeIgniter4 version."

And that project have setAutoRoute() set to false:
https://github.com/codeigniter4projects/...es.php#L16

There are no selection on how the auto route feature works. It either on or off.
Reply

#5
Okay, so I downloaded CI 4.0.3 and tested it. setAutoRoute() is set to true by default. This is the (imo, problematic) result:

Code:
http://localhost/ci/public/                 200
http://localhost/ci/public/home             200
http://localhost/ci/public/home/index       200
http://localhost/ci/public/home/index/foo   200 (foo -> unexpected parameter, should return 404)

Then I switched setAutoRoute() to false. This is the (again imo, unacceptable) result:

Code:
http://localhost/ci/public/                 200
http://localhost/ci/public/home             404
http://localhost/ci/public/home/index       404
http://localhost/ci/public/home/index/foo   404 (as expected, but the two above also don't work, bummer)

Since auto route is off, I need to set explicit routes. If I do $routes->get('/home', 'Home::index'), this is the result:

Code:
http://localhost/ci/public/                 200
http://localhost/ci/public/home             200 (works now because it's set explicitly)
http://localhost/ci/public/home/index       404
http://localhost/ci/public/home/index/foo   404

I can't work with any of this. Auto route is a life-safer. Having to set routes for every URL is a pain (I'm relatively new to FWs, so what do I know Smile )

I think, for the time being, I'll do custom argument check in the methods. Sadly, I don't have much experience to know which one is better.
Reply

#6
A side query, does that mean that every published app on the net that uses CI 3 suffers from this issue? That I can just go to some CI app and visit site/login/blabla and still view the site/login page unless they modified the Router.php? I can just make up random, possibly harmful, URLs such as site/login/hahahihi and post these on the net, and they'll still work! Isn't this a problem? Am I over worrying? Smile
Reply

#7
If you classifies providing a convenient way of getting parameters to your method as an issue, then yes.
All parameters are sanitized, so unless people turn that feature off, you can't do any harm to the application itself.
Reply

#8
I thought I should expand on this issue/topic by providing some examples just the make the case clear.

Here are some live URLs that works as expected:

Code:
URL                                             result  description
---------------------------------------------------------------------------
https://codeigniter.com/download                200
https://codeigniter.com/download/foo            404     unexpected "/foo"
https://stackoverflow.com/tags/php/info         200
https://stackoverflow.com/tags/php/info/foo     404     unexpected "/foo"
https://github.com/explore                      200
https://github.com/explore/foo                  404     unexpected "/foo"

Here are some URLs from my app:

Code:
URL                         default     expected    description
-------------------------------------------------------------------------------------
site/staff/info             200         404         info must have a single argument
site/staff/info/1           200         200
site/staff/info/1/edit      200         200         info may have a second argument
site/staff/info/1/edit/bar  200         404         unexpected third argument: "bar"
site/staff/info/1/foo       200         404         unexpected argument "/foo"
site/staff/info/1/foo/bar   200         404         unexpected arguments "/foo/bar"

Notice the difference in results (default vs expected).

While the URL to controller mapping/routing is a useful feature, I think it can be improved.

To get around this unexpected arguments to the URL/controller methods, I created a method in MY_Controller:

PHP Code:
/**
 * Controls the number of arguments a method expects.
 */
protected function arguments(int $min 0int $max 0, array $caller null) {
    if ($max == && $min != 0) {
        $max $min;
    }
    $caller ??= debug_backtrace(02)[1];
    $caller_arg_count count($caller["args"]);
    if ($caller_arg_count $min || $max $caller_arg_count) {
        show_404();
    }


and I use it in the controller methods:

PHP Code:
class Staff extends MY_Controller {
    
    
public function info(string $staff_id null)  {
        
        $this
->arguments(12); // must have 1 arg (staff id); may have a second argument (edit) 

This provides the expected behaviour.

CI is the first FW that I've used, and I haven't used any other FW, yet. So I might be going at this the wrong way. I don't know how other FWs deal with this.

The suggested solution (turning auto route off) seems like a bad idea to me, if the application has some tens of URLs that match controllers (class/method) one-to-one. I wouldn't want to bother with setting explicit routes. Again, what do I know Smile
Reply

#9
Yeah, I know what you are expecting the framework to do, but it dosen't know that you want X parameters instead of Y. So it gives you all of them. Sure if more people wan't this kind of behavior or better yet submit a valid solution to said problem. It's likely it gets implemented into the framework.

As with other PHP Framework, you are required to manually set all your routes. Personally I can't mention another framework that have an auto route feature.
Reply

#10
Oh, so in other words, the smart thing to do is to get accustomed to manual routing.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.