Another day at the office



  • foreach ($_GET as $key=>$value) {       
         $empty="";
          if(!empty ($value)){               
               if (stristr($key,'attribute_')==true){
                    $output = str_replace("attribute_",$empty,$key);

                    //Some other functionality

                }

          }

    }


    This is on it's way to our production codebase.


  • 🚽 Regular

    Give me the URL. I want to call its page with the query: ?attribute_Paula=Brillant

    Or something like that.



  • @DOA said:

    This is on it's way to our production codebase.
     

    Did you attempt to stop it?



  • I'ts less ugly than that (included at the top of every file)

    foreach($_GET as $name => $val) { eval("\${$name} = $val;"); }
    foreach($_POST as $name => $val) { eval("\${$name} = $val;"); }
    foreach($_COOKIE as $name => $val) { eval("\${$name} = $val;"); }
    foreach($_SESSION as $name => $val) { eval("\${$name} = $val;"); }
    foreach($_FILES as $name => $data) {
        eval("\${$name} = {$data['name']};");
        eval("\${$name}_tmpName = {$data['tmpName']};");
        eval("\${$name}_type = {$date['type']};");
    }
    


  • @dhromed said:

    Did you attempt to stop it?
    I'll have a word with my team at some point. With a cluebat. It'll be a while before this snippet goes live.



  • @ltouroumov said:

    foreach($_GET as $name => $val) { eval("${$name} = $val;"); }
    Someone never heard of variable variables.
    However, this would be a common way of providing backwards compatibility for scripts that expected register_globals to be on. It's also great for accidental security holes.



  • Easiest way to get around register_globals being off:

    extract($_REQUEST);



  •  So, the WTF is the injection vulnerability?


  • 🚽 Regular

     @GoatRider said:

    Easiest way to get around register_globals being off:

    extract($_REQUEST);

    God, I hate it when people talking about "getting around register_globals being off" as if it's some major roadblock in their development. I don't understand what is so hard about being specific about what you will accept as query parameters in the URL by using $_REQUEST, $_GET, or $_POST.



  • @RHuckster said:

     @GoatRider said:

    Easiest way to get around register_globals being off:

    extract($_REQUEST);

    God, I hate it when people talking about "getting around register_globals being off" as if it's some major roadblock in their development. I don't understand what is so hard about being specific about what you will accept as query parameters in the URL by using $_REQUEST, $_GET, or $_POST.

    I've never really understood the value of $_REQUEST. Are we really to believe that there are sites out there that have forms whose method is variable (unknown at design time whether it's "GET" or "POST")? Or is it to make it easier to generalize form handling to work whether the form with the "favorite_color" field is rendered with a "GET" or a "POST"? Why the hell wouldn't you make your method usage explicit?



  • @DOA said:

    foreach ($GET as $key=>$value) {       
         $empty="";
          if(!empty ($value)){               
               if (stristr($key,'attribute
    ')==true){
                    $output = str_replace("attribute_",$empty,$key);

                    //Some other functionality

                }

          }

    }


    This is on it's way to our production codebase.

    So what does the "//Some other functionality" do with $output? As it is, it looks harmless. Stupid, but harmless. If it's assembling a SQL query or something with the cleaned key name, then that is potentially harmful. But if it's just using the cleaned key name as an index into an associative array or something, eh.



  • @ltouroumov said:

    I'ts less ugly than that (included at the top of every file)

    foreach($_GET as $name => $val) { eval("\${$name} = $val;"); }

    ?d=0;print%20file_get_contents($_SERVER[SCRIPT_FILENAME])



  • @DOA said:

    This is on it's way to our production codebase.
     

    I never actually wanted to show anyone, but it may make you feel better. Piece of our actual codebase, saving data from javascript-driven dynamic form to create/edit answer sheets.

     

      foreach($_POST as $key => $val)
      {
        if(preg_match("/txtQ([0-9]*)$/", $key)) //it's a question
        {
          $qOrder = $qOrder + 1;
          $question = htmlspecialchars($val, ENT_QUOTES);

          mysql_query("INSERT INTO Questions (TestID, QuestionOrder, Question)
            VALUES ($tID, $qOrder, '$question');") or die(mysql_error());

          //i'll need question's id
          $qID = mysql_insert_id();
        }
        elseif(preg_match("/txtQ([0-9]*)A([0-9]*)Text/", $key)) //answer text
        {
          //name of score field
          $pts = str_replace("Text", "Points", $key);

          $text = htmlspecialchars($val, ENT_QUOTES);
          $points =(int) $_POST[$pts];

          mysql_query("INSERT INTO Answers (TestID, QuestionID, Text, Points)
            VALUES ($tID, $qID, '$text', $points);") or die(mysql_error());
        }
        elseif(preg_match("/txtR([0-9]*)Min/", $key)) //result lower bound
        {
          //rest of the data fields
          $mx = str_replace("Min", "Max", $key);
          $ttl = str_replace("Min", "Title", $key);
          $txt = str_replace("Min", "Text", $key);

          $minPoints =(int) $val;
          $maxPoints =(int) $_POST[$mx];
          $title = htmlspecialchars($_POST[$ttl], ENT_QUOTES);
          $text = htmlspecialchars($_POST[$txt], ENT_QUOTES);

          mysql_query("INSERT INTO Results (TestID, MinPoints, MaxPoints, Title, Text)
            VALUES ($tID, $minPoints, $maxPoints, '$title', '$text');") or die(mysql_error());
        }
      }


  • @toth said:

    Are we really to believe that there are sites out there that have forms whose method is variable (unknown at design time whether it's "GET" or "POST")?
     

    probably not, but i've seen some pages that decide whether to post or get the form (or even the variables separately) depending on how you navigated there, or some other arcane arbitrary variable. it was creating pretty unpredictable patterns.



  • @toth said:

    I've never really understood the value of $_REQUEST. Are we really to believe that there are sites out there that have forms whose method is variable (unknown at design time whether it's "GET" or "POST")? Or is it to make it easier to generalize form handling to work whether the form with the "favorite_color" field is rendered with a "GET" or a "POST"? Why the hell wouldn't you make your method usage explicit?

    Yes, plenty.  Consider a script that searches a database for a list of strings.  If you only use GET requests, your queries will be restricted to a few thousand characters (exact limits depending on the browser and webserver used, plus any proxies in between).  For many applications, this may not always be enough.  On the other hand, if you only use POST, you can't link to search results with a simple <a> tag; the best you can do without JS is to use a form with a bunch of hidden fields and a submit button.  This is a pain in the ass.

    More to the point, sooner or later you'll find yourself wanting to use GET for a script you wrote to use POST, or vice versa.  Writing method-neutral code to begin with (except in the very rare cases where the difference actually matters) will save you trouble later.

    Perl's venerable CGI.pm, for all its many WTFs, got a few things right.  One is that, if you really wanted to know whether a given parameter was given in the URL or POSTed, you'd really have to work at it.  By default, the param() method returns both of them mixed together, and that is as it should be.



  •  Except semantically GET and POST are entirely different things and should be used interchangeably.



  • @pbean said:

    Except semantically GET and POST are entirely different things and should be used interchangeably.
    Yeah, in theory they are.  And if there was a way to attach form data into a GET request without cramming it all onto the URL, people might actually use them as intended.

    Anyway, the major semantic difference is that GET requests are supposed to be idempotent.  Mind you, there's nothing saying that POST requests aren't allowed to be idempotent too.  So there may occasionally be reasons to only accept POST requests, but never any reason to only accept GET.

    Anyway, even then, using $_GET and $_POST is the wrong way to do it.  A POST request with some parameters passed in the URL is still a POST request, after all.  If you really care about what the request method is, look at $_SERVER['REQUEST_METHOD'].



  • @vyznev said:

    More to the point, sooner or later you'll find yourself wanting to use GET for a script you wrote to use POST, or vice versa.  Writing method-neutral code to begin with (except in the very rare cases where the difference actually matters) will save you trouble later.

    s/$_GET/$_POST/g

    Is that really so hard?



  • @toth said:

    I've never really understood the value of $_REQUEST. Are we really to believe that there are sites out there that have forms whose method is variable (unknown at design time whether it's "GET" or "POST")? Or is it to make it easier to generalize form handling to work whether the form with the "favorite_color" field is rendered with a "GET" or a "POST"? Why the hell wouldn't you make your method usage explicit?
    $_REQUEST can have $_COOKIE and $_SESSION in it too.



  • @vyznev said:

    Anyway, the major semantic difference is that GET requests are supposed to be idempotent.  Mind you, there's nothing saying that POST requests aren't allowed to be idempotent too.
     

    these are some fascinating news to me, sir, but I don't really understand its meaning. What exactly do you mean by GET requests being/supposed to be idempotent?

    @vyznev said:

    Anyway, even then, using $_GET and $_POST is the wrong way to do it.  A POST request with some parameters passed in the URL is still a POST request, after all.

    how do you do that?

    (are these things that most of people know and i'm just clueless, or is it one of typical WTF forum's "this is how it should be done, but nobody knows it"?)



  • @SEMI-HYBRID code said:

    @vyznev said:

    Anyway, the major semantic difference is that GET requests are supposed to be idempotent.  Mind you, there's nothing saying that POST requests aren't allowed to be idempotent too.
     

    these are some fascinating news to me, sir, but I don't really understand its meaning. What exactly do you mean by GET requests being/supposed to be idempotent?

    Means it's safe to cache a GET result because no side-effects should occur from one. Eg: admin/?action=delete&id=42 is bad because it does something (deletes whatever id42 is), but search/?q=ponies is good because it can be safely cached without disabling functionality of the site.

    @SEMI-HYBRID code said:

    (are these things that most of people know and i'm just clueless, or is it one of typical WTF forum's "this is how it should be done, but nobody knows it"?)
    This is standard RESTful behavior. As HTTP is supposed to be RESTful breaking that makes dealing with HTTP more of a pain than it already is.



  • @SEMI-HYBRID code said:

    @vyznev said:
    A POST request with some parameters passed in the URL is still a POST request, after all.
    how do you do that?
    <form method="POST" action="script.php?foo=bar">



  • @Lingerance said:

    @SEMI-HYBRID code said:

    @vyznev said:

    Anyway, the major semantic difference is that GET requests are supposed to be idempotent.  Mind you, there's nothing saying that POST requests aren't allowed to be idempotent too.
     

    these are some fascinating news to me, sir, but I don't really understand its meaning. What exactly do you mean by GET requests being/supposed to be idempotent?

    Means it's safe to cache a GET result because no side-effects should occur from one. Eg: admin/?action=delete&id=42 is bad because it does something (deletes whatever id42 is), but search/?q=ponies is good because it can be safely cached without disabling functionality of the site.
     

    See also the Spider of Doom.



  • @vyznev said:

    <form method="POST" action="script.php?foo=bar">
     

    ...how much of a wtf it is that i've been programming pages for around 4 years by now, using this, and believing it sends form's content by post and url parameters by get?



  • @Lingerance said:

    Eg: admin/?action=delete&id=42 is bad because it does something (deletes whatever id42 is), but search/?q=ponies is good because it can be safely cached without disabling functionality of the site.

    oh, i know this, but i probably never heard the term for it. thanks



  • @SEMI-HYBRID code said:

    @vyznev said:

    <form method="POST" action="script.php?foo=bar">
     

    ...how much of a wtf it is that i've been programming pages for around 4 years by now, using this, and believing it sends form's content by post and url parameters by get?

    The method attribute of <form> refers to which kind of HTTP request is sent when the submit button is pressed. Links always result in a GET request, forms can use either GET or POST. A single request can only have one type though, so while a POST request may have parameters in its URL, it's still a POST request.

    I've only used CGI myself, and there the URL parameter part is called QUERY_STRING regardless of request type, while the content of the request is read from stdin (only available for POST requests, as GET requests never have content).



  • @SEMI-HYBRID code said:

    @vyznev said:
    <form method="POST" action="script.php?foo=bar">
    ...how much of a wtf it is that i've been programming pages for around 4 years by now, using this, and believing it sends form's content by post and url parameters by get?
    What may be confusing is that PHP, for example, will put URL parameters into the array named $_GET regardless of what the actual request method is.  It's really just the name of the array that's misleading.  There's still only one request (per form submission), and it only has one request method, which may be GET or POST (or HEAD or PUT or whatever) but not both.



  • @SEMI-HYBRID code said:

    @vyznev said:

    <form method="POST" action="script.php?foo=bar">
     

    ...how much of a wtf it is that i've been programming pages for around 4 years by now, using this, and believing it sends form's content by post and url parameters by get?

    At least as much a WTF as I am. I looked at it and assumed the same thing. Well, I mean, I didn't think it made two separate requests, but I thought URL parameters would be placed in the GET collection on the server even when POSTed (which apparently is what PHP does, although I suppose that behavior is backend-specific).



  • @toth said:

    @SEMI-HYBRID code said:

    @vyznev said:

    <form method="POST" action="script.php?foo=bar">
     

    ...how much of a wtf it is that i've been programming pages for around 4 years by now, using this, and believing it sends form's content by post and url parameters by get?

    At least as much a WTF as I am. I looked at it and assumed the same thing. Well, I mean, I didn't think it made two separate requests, but I thought URL parameters would be placed in the GET collection on the server even when POSTed (which apparently is what PHP does, although I suppose that behavior is backend-specific).

    That means you guys have never looked at a raw HTTP request send over the wire, because if you had you'd know a POST is passed exactly the same way as a GET (name=value pairs separated by ampersands). The only difference is that GET passes its parameters through in the URL, while POST passes them through in the HTTP headers.

    Also anyone who uses register_globals = on should be shot, and anyone who attempts to mimic the effect of that setting should be burned, disemboweled, and then shot.



  • @The_Assimilator said:

    That means you guys have never looked at a raw HTTP request send over the wire, because if you had you'd know a POST is passed exactly the same way as a GET (name=value pairs separated by ampersands). The only difference is that GET passes its parameters through in the URL, while POST passes them through in the HTTP headers.

    Uh, yeah, I knew that. What I was actually assuming was that the server code would place them in the separate parameter collections based on whether they were in the URL or the request body. Which, as I said, is apparently what PHP actually does.



  • @vyznev said:

    What may be confusing is that PHP, for example, will put URL parameters into the array named $_GET regardless of what the actual request method is
    Out of curiocity, anyone know if this is PHP specific?

     

     

    This question has an open bounty worth +100 reputation from DOA ending in 2 years.

     

     



  • @DOA said:

    @vyznev said:
    What may be confusing is that PHP, for example, will put URL parameters into the array named $_GET regardless of what the actual request method is
    Out of curiosity, anyone know if this is PHP specific?
     

    AFAIK, this is common to every system out there.

    When you POST a form to an action that has querystring parameters in it, you get the QS params with the framework object that handles the QS, and the POST params with the POST object. In ASP Classic, for example, that would be Request.QueryString() and Request.Form().

    I would be awesomely suprised if any system did this differently.

    I'm not sure off the top of my head what happens when you GET a form to an action that has QS params. I should test that, but I can't right now, and won't later. I suppose you lose the action's parameters because they get overwritten with the form fields. That would make sense, as you messed it up and the system's not to blame.

    I just remembered an old solved-problem issue we had in our CMS where you action'd to a generated url with GET, and then it would barf because you frogot to add the CMS magic parameters as hidden fields to the form. So yeah, you totally lose the action's parameters when you GET a form.



  • @The_Assimilator said:

    That means you guys have never looked at a raw HTTP request send over the wire, because if you had you'd know a POST is passed exactly the same way as a GET (name=value pairs separated by ampersands). The only difference is that GET passes its parameters through in the URL, while POST passes them through in the HTTP headers.

    And you haven't looked at enough raw HTTP requests...

    C: POST /the_url HTTP/1.1
       User-Agent: curl/7.11.1 (i686-pc-cygwin) libcurl/7.11.1 OpenSSL
       Host: www.example.com
       Content-Length: 38421
       Expect: 100-continue
       Content-Type: multipart/form-data; boundary=--------------------
    
    S: HTTP/1.1 100 Continue
    C: ------------------------------
       Content-Disposition: form-data; name="a"
    
       value_for_a
       ------------------------------
       Content-Disposition: form-data; name="b"
    
       value_for_b
       ------------------------------
       Content-Disposition: form-data; name="c"; filename="mydocument.doc"
       Content-Type: application/octet-stream
    
       ...

    http://www.redmountainsw.com/wordpress/archives/multipartform-data-over-the-wire-example



  • You might want to read up on how stuff works

    Paraphrasing from the above link, if the encoding in a form is "application/x-www-form-urlencoded" (which is the default), it is encoded like a query string. If it's encoded "multipart/form-data", then it's encoded in segments as above.



  • I know. I said enough because he's seen it one way but not the other.


Log in to reply