If you're just passing stuff from one page to the next like that, why not just store the data in the session in the first place? Then it doesn't get sent out to the client at all to potentially get corrupted.

    Let's say that you're designing an online catalog. You potentialliy could be listing 40 items in the catalog for the user to select (click on) one. Those links would be "index.php?showItem=1", "index.php?showItem=2", etc.. They could also click on "next" or "previous" which would say "index.php?page=10" or "index.php?page=12".

    On the pages where I use this, I list daily data for 18 facilities. That's 18 tables - one for each facility, and each table is 30 columns across - one for each day of the month. The first row of each table shows the date. Each of those dates is a link with an href of "index.php?facility=7&date=2004-01-02", "index.php?facility=7&date=2004-01-03", etc. and those links take you to a "details" page for that particular day, for that facility. I don't know how it's possible to store all of that in the session, or even if it's necessary, or efficient, especially when I don't know where the user will want to go. In fact I'm positive that that's the wrong way to do it.

    Session variables would be the place to store things like "userLoginName", "userFirstName", "userLastName" etc... variables that are constant throughout the session.

      So .... what's the problem then? So what if they do alter the fields? Obviously you're going to be checking that $GET['facility'] is an integer, and that it is in the right range, that $GET['date'] really is of the form nnnn-nn-nn and parses as a genuine date. If they change a field that doesn't validate they get an error page. If they change a field to something that does validate they get a different page from the one linked to. What did they expect when they changed the URL? 🤷

      So what, exactly, are you trying to protect here?

      (
      As for the one-time pad:
      $facility['jweoifjwiew98fw98fh']='7';
      $date['398u9gtu89uy98uy']='2004-01-03';

      <a href="index.php?facility=jweoifjwiew98fw98fh&date=398u9gtu89uy98uy">

      $real_facility = isset($facilities[$GET['facility']]) ? $facilities[$GET['facility']] : null;
      $real_date = isset($dates[$GET['date']]) ? $dates[$GET['date']] : null;
      )

      And no, session variables don't have to be constant throughout the session. They just have to persist (until you destroy them). And sure sessions can contain several hundred items.

        <?php
        session_start();
        
        // Require encryption file
        require("/functions/encryption.inc.php");
        
        // Query for all active facilities alphabetically
        $query = "SELECT id, name FROM facility WHERE active ='y' ORDER BY name";
        $result = mysql_query($query, $con);
        
        // Loop through all facilities
        while($row = mysql_fetch_array($result))  {
        
        // Only display facilties where you have rights
        if(allowedToGo($row['id'])  {
            echo('<a href="http://www.me.com/showFacility.php?'. 
                encrypt($key, 'facility='. $row['id']) .'">'. $row['name'] .'</a><br />');
        }
        }
        

        How many facilities are there? Could be 9, could be 4261. How big is your one time pad? You want to store all of those variables in the session when you'll only ever need one of them? That just seems like an enormous waste of space (and work) to me. And if I come back at a later date to add a feature, I have to waste time coding the one time pad and all of that. With the encrypted URL, you don't have to do that. Just encrypt() or updateURL() whatever you want to add, and it just flows to the target nice and neat.

        What I want to prevent is someone typing in "?facility=7" when they don't have rights to view that facility, or 'startDate=1950-13-92' and causing something strange to happen on a page that was written by our jr. programmer. Obviously, they won't be able to do either with your one time pad example either.

        Also, by doing it with an encrypted URL, you can't even see what the variables are, let alone change them. I could pass "lukesFather=DarthVader" and you would have no idea. By the way, I could also pass "lukesFather=Darth Vader" and because of the way I'm setting up the URL, it would work just fine even with the space.

        Encrypting the URL also prevents people from adding their own variables to the end of a URL to try to affect what happens on the page. I know it's bad programming practice to not initialize variables properly and all of that, but when you're working with somewhat less skilled programmers like I am, this gives me nice peace of mind knowing that our users can't take advantage of a hole like that.

        And no, session variables don't have to be constant throughout the session. They just have to persist (until you destroy them).

        Of course, you're right about that. I mis-spoke on that. Sorry, I think I was still half asleep. 🙂

          Another example would be if a user is allowed to go to facility A to view the house keeping budget, and facility B to view the maintenance budget, but NOT the other way around, a moderately savvy user could figure out how to trick the page to take them where they're not allowed to go with your one time pad pretty easily.

            marshallm wrote:

            How big is your one time pad?

            Exactly as big as it needs to be. It's only used one time (hence the name) - i.e., for one response/request - and then discarded. The next one will be different.

            marshallm wrote:

            a moderately savvy user could figure out how to trick the page to take them where they're not allowed to go with your one time pad pretty easily.

            Example?

            marshallm wrote:

            What I want to prevent is someone typing in "?facility=7" when they don't have rights to view that facility, or 'startDate=1950-13-92'

            Which is why you should always validate input data, yes?

            and causing something strange to happen on a page that was written by our jr. programmer.

            Oh, I get it now; this is code for people who don't think to validate their input data.

            So your argument amounts to: "I use MD5 and CAST_256 encryption from the mcrypt library and a hundred hundred lines of code so that I don't have to validate my input data or use urlencode()".

            Have you spotted the satire yet?

              Example?

              //If...
              <a href="index.php?facility=jweoif&budget=398u9gtu8">facility a, housekeeping budget</a>
              <a href="index.php?facility=gwhbeeh&budget=nbdu89hde">facility b, maintenance budget</a>
              // Then...
              <a href="index.php?facility=gwhbeeh&budget=398u9gtu8">facility b, housekeeping budget</a>
              

              Which is why you should always validate input data, yes?

              Yes! But that is a way for users to start knocking on your door. Why even show them the door?

              Oh, I get it now; this is code for people who don't think to validate their input data.

              No, but that's certainly a nice side effect! 🙂

              So your argument amounts to: "I use MD5 and CAST_256 encryption from the mcrypt library and a hundred hundred lines of code so that I don't have to validate my input data or use urlencode()".

              Not quite. First of all, I include one file at the top of all of my pages, which is usually itself included from a header include file. I set it up once, and don't worry about it. And it seems pretty easy to me to just say "encrypt($key, "facility=". $row['id']). Especially when our COO calls me and asks me to do something which requires me to add, for example, a date variable in the URL. In which case I add "&date=". date('Y-m-d') to the above line, and I'm done. So I would say that my argument is: "I use the mcrypt library to easily pass variables through URL links in a way that a) does not allow the user to determine anything about how my program is working, or how data is stored, and b) makes it extremely difficult for the user to try to fool a page into doing something it's not supposed to do."

              We're both in effect doing the same thing, but encrypting the entire URL string not only hides the values of the variables, but also the variable names themselves and how many variables there are. The users can not determine how they're getting from point A to point B, and because of that, they have little hope of changing course. I also happen to think when dealing with something like HIPAA, showing the user something like "patientID=12345" in the URL is VERY bad. Doing it my way, they have no way of knowing if there is a variable that holds the patient ID, or if there is - what it's called, let alone what its value is.

              But then... maybe you're right, and I'm just paranoid. 😉

                marshallm wrote:

                Yes! But that is a way for users to start knocking on your door. Why even show them the door?[/code]Because they're the ones who are supposed to be using these doors - the site exists for their benefit. I go out into a carpark and I see plenty of doors. But they're all locked and I've only got keys to one set of doors - the set I'm allowed to open. I can knock on the rest all day and nothing will happen. (Well, if I knock hard enough some will start complaining).

                We're both in effect doing the same thing, but encrypting the entire URL string not only hides the values of the variables, but also the variable names themselves and how many variables there are.

                I could certainly do that (encrypt the entire querystring) but I reckon "18 facilities, 30 columns, that's potentially 540 combinations to list, though not all of them are relevant all the time - but whatever, I still have to anticipate every single URL they could possibly be allowed to ask for in the given context. That's up to 540 distinct URLs I have to generate, encrypt, and list on the page for the user to have to choose from. I can't provide a form-based interface. And how would I describe it in the link text? 'Facility 5, Column 12'? Well, that certainly hides those fields."

                showing the user something like "patientID=12345" in the URL is VERY bad. Doing it my way, they have no way of knowing if there is a variable that holds the patient ID, or if there is - what it's called, let alone what its value is.

                So encrypt the field names as well. Again, I couldn't be bothered above; I have written medical software for clinicians and they expect there to be "Patient ID" (their NHI Number) which is unique for each patient (and even displayed on the screen because they can't rely on the patient's name to ensure they're looking at the right person's records). Of course, they could reason that such a thing must exist, otherwise how would their software know which patient's data is being requested?

                  I guess we'll just agree to disagree, but anyway, there's two ways to answer the original question.

                  Cheers!
                  Mark

                    Correct - there are two (encrypting the URL and validating input); I'm not serious about the one-time pad. I just made it up as something that compared with reversible encryption is more secure, more flexible, and doesn't require as much computational overhead.

                      Ok, first, I'm not sure how "validate your input" answers the question of how to prevent users from modifying the URL from one legal value to another presumably legal value, but whatever.

                      And secondly, I'm also not sure how:

                      // This:
                      <a href="index.php?facility=jweoif&budget=398u9gtu8">facility a, housekeeping budget</a>
                      <a href="index.php?facility=gwhbeeh&budget=nbdu89hde">facility b, maintenance budget</a>
                      
                      // Is more secure or flexible than this:
                      <a href="index.php?16d93ba811be01928ab36aef3b19a03">facility a, housekeeping budget</a>
                      <a href="index.php?b2876a511b20912b344b12973913bca">facility b, maintenance budget</a>
                      

                      ...but again, whatever.

                        If the modified value is legal then what's the problem?

                        marshallm wrote:

                        ...but again, whatever.

                        Exactly - whatever:

                        Weedpacket wrote:

                        I could certainly do that (encrypt the entire querystring) but I reckon "18 facilities, 30 columns, that's potentially 540 combinations to list, though not all of them are relevant all the time - but whatever, I still have to anticipate every single URL they could possibly be allowed to ask for in the given context. That's up to 540 distinct URLs I have to generate, encrypt, and list on the page for the user to have to choose from. I can't provide a form-based interface. And how would I describe it in the link text? 'Facility 5, Column 12'? Well, that certainly hides those fields."

                        Security? Well, breaking the encryption would require either gaining access to the hosting server and getting a hold of the pad or predicting the RNG's behaviour.

                        Flexibility? Well, like I said, I could encrypt the entire querystring or individual fields. I don't have to build the query string in any particular fashion (the only difference would be call garble('field',$value) instead of urlencode($value)), I don't have to encrypt everything if I don't want to, and (as I noted) I can still have a form-based UI.

                          Weedpacket wrote:

                          If the modified value is legal then what's the problem?

                          The problem is that you wouldn't know that someone is trying to modify it. I want to know if someone is trying to modify stuff, that way the code I have can take measures to ban the person (through different means probably already known to you Weedpacket).

                          I'm with marshallm on this one and I intend to encrypt all the URL data in the web site I'm about to develop.

                          FYI: php|architect has a new PHP security book. I'm only half way through it and I know all the stuff I've read so far. It's got quiet a few grammar errors and I've noticed one coding error so far, but I think it's still good for beginners to learn about security:

                          http://www.phparch.com/shop_product.php?itemid=98

                          🙂

                            Thanks for that, toplay.

                            How will you be encrypting your URL data? Something similar to my code, or do you have a different method?

                              I guess we have a different conception of what qualifies as "legal", then. In my book "legal" depends not only on the values in the query itself, but anything else that's relevant - the user making the query, the IP the query is coming from, and so forth.

                              So if the user takes a query for a resource they're allowed to see, and modifies it to refer to a resource they're also allowed to see, then what's the problem in allowing them to see it? If there's a risk that something will break if a value is modified, then it shouldn't be in the query in the first place.

                                Weedpacket wrote:

                                I guess we have a different conception of what qualifies as "legal", then.

                                marshallm wrote:

                                prevent users from modifying the URL from one legal value to another presumably legal value

                                I think we agree on that.

                                Weedpacket wrote:

                                So if the user takes a query for a resource they're allowed to see, and modifies it to refer to a resource they're also allowed to see, then what's the problem in allowing them to see it?

                                I do NOT want my users doing that. Maybe you're ok with it, and that's fine. I'm not ok with it (here's where you say "that's fine"). It's a programming design decision that I'm making to encrypt the URL, which will make it and the entire program MORE secure and predictable than it is without the encryption. I do not want users looking at the URL and using what they see as direction for how to start attacking the program. Or how to start attacking a different program that's using the same database. Whether they're successful at attacking or not, I don't want them to have that information. I also don't want users getting into the habit of hacking the program to do whatever they want. I want them to learn to use the program the way it was designed. If they're allowed to get there, then there's a way to get there through the program.

                                It seems we differ on programming style decisions, and level of necessary security. Which is fine. 🙂

                                  Write a Reply...