Forum Moderators: coopster

Message Too Old, No Replies

Now that parse str() without a "result" is deprecated.

         

csdude55

11:31 pm on Dec 31, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Is there an alternative other than parsing it to an array, then looping through the array manually? Eg, something like:

$string = "foo=a&bar=b";
parse_str($string, $output);

foreach ($output as $key => $val)
$$key = $val;


I was using this to save a current query string in a cookie, then I could loop them through some things and take them back where they were with a slightly modified query string. I could rewrite the whole script to use an array instead of scalar variables, but it'd be a whole lot easier if I could just change this one thing...

On the deprecation:

[php.net...]

w3dk

12:31 am on Jan 1, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



foreach ($output as $key => $val)
$$key = $val;


The extract() PHP function does the same thing.

However, you should not apply this to untrusted data (without taking additional measures), like a "query string" that is passed on the request, for the same reasons as why the parse_str() function without the 2nd argument is deprecated.

If you were reliant on this "feature" before (and applying it to the passed "query string" as suggested) then it means your script was potentially vulnerable to a XSS attack.

Much better to update your script to use the array instead, or simply extract "known" variables one by one as required:


$varname = $output['varname'] ? null;

csdude55

6:28 am on Jan 1, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'd forgotten about extract(), thanks :-) So:

$string = "foo=a&bar=b";
parse_str($string, $output);
extract($output);


As I'm looking through all of my scripts, I used parse_str() in a dozen different ways... when I used Ajax to open PHP scripts and needed a way to parse the variables is a good example.

A better example, though, is on my forms. When the form loads, I read MySQL to populate the fields. Then they change fields as needed, submit, and the processing function updates MySQL. Well, there are times when the processing function fails for some reason or another, so I send them back to the form with GET params that populate the fields instead; obviously, so they don't lose whatever they typed up.

Example (just typed up to show you what I mean, this isn't real):

parse_str($_SERVER['QUERY_STRING']);

if (!$foo) {
$query = sprintf("SELECT foo FROM table WHERE username='%' LIMIT 1",
mysqli_real_escape_string($dbh, $username));

$sth = mysqli_query($dbh, $query);

if ($sth !== false)
list($foo) = mysqli_fetch_row($sth);
}

echo <<<EOF
<form action="whatever.php">
<label for="foo">Foo</label>
<input type="text" name="foo" id="foo" value="$foo">
</form>

EOF;


You can see that, without parse_str(), I have to completely redesign a system to overwrite the MySQL data when they have an error message.

Nothing submitted through the query string is written anywhere, it just populates the fields no different than if they had typed it.

(I tried to show some of my security stuff, but the site throws an error on it)

Am I overlooking a security hole by doing it this way?

w3dk

11:54 am on Jan 1, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



$varname = $output['varname'] ? null;


NOTE: The single-? above should be a double-? - it's the null coalescing operator. (This forum appears collapse double-? to single-?.)

(@phranque Needs a clean-up please. Thanks.)

w3dk

12:28 pm on Jan 1, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



without parse_str(), I have to completely redesign a system


Not really, just a few extra lines would "securely" workaround the problem and make the code self-documenting as it's clearer where these variables come from:

parse_str($_SERVER['QUERY_STRING'],$output);
$foo = $output['foo'] ?? null;
$bar = $output['bar'] ?? null;



extract($output);
parse_str($_SERVER['QUERY_STRING']);


The "problem" with these two statements is that the extracted variables will overwrite any that are already defined in the current scope with the same name. So, if I (maliciously) passed a "dbh" parameter in the query string, it would break your DB connection. The extract() function takes a 2nd argument that allows you to control this. And passing the 2nd argument to the parse_str() function prevents this.

[edited by: w3dk at 1:24 pm (utc) on Jan 1, 2021]

JorgeV

1:16 pm on Jan 1, 2021 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month



Hello,

@w3dk is right. The reason that the parse_str function has been modified, was because of bad and unsafe practices of some.

PHP is easy to use language, but if you are not rigorous, it can turn terribly dangerous. This is why the PHP team is trying to strengthen the language structure.

Self teaching is great, but, in my opinion, this is good to take programming lessons. This learn you methods of working, and also best practices. When you have a good basis of programming, you can achieve things faster, safer and makes it easier to evolve your code.

csdude55

6:36 pm on Jan 1, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Not really, just a few extra lines would "securely" workaround the problem and make the code self-documenting as it's clearer where these variables come from:

Yeah, but in one of the forms that's 32 variables to manually declare :-( I didn't look at the others, but I think that's my biggest one. That's a lot of opportunity for typos, too.

The "problem" with these two statements is that the extracted variables will overwrite any that are already defined in the current scope with the same name. So, if I (maliciously) passed a "dbh" parameter in the query string, it would break your DB connection. The extract() function takes a 2nd argument that allows you to control this. And passing the 2nd argument to the parse_str() function prevents this.

But in my case, overwriting the existing variable was the whole point! LOL

I'm not sure if I understand what you mean for dbh. If someone maliciously sent a dbh parameter, it would just break the connection on that one page and session, right? So all that would be affected would be the person or script that did it. Or is there opportunity for more problems by overwriting the dbh connection?

If that's the "only" problem, couldn't I just forbid pages with dbh as a query parameter?

I've read a lot of articles on it since yesterday, but none of it REALLY seems like a big deal. They could affect the output on the page they're looking at, sure, but I don't really see how that matters. What am I misunderstanding?

Self teaching is great, but, in my opinion, this is good to take programming lessons. This learn you methods of working, and also best practices. When you have a good basis of programming, you can achieve things faster, safer and makes it easier to evolve your code.

@JorgeV, sadly, there's no such thing as "advanced programming" anywhere near me! Around 10, maybe 15 years ago I actually taught Advanced Programming at the local community college, which was really a Perl class that touched on PHP in the last few weeks. It was the last class they took before graduating, but I swear that half of the curriculum was "what are variables", "what are arrays", etc. And most of the students honestly didn't know! So it was super remedial, and nothing at all like what I would be able to use.

Not even kidding, one of the students told me that they had never once gotten a program to successfully work. In any class, ever. And she was about to graduate!

My final exam was a take-home, open-book open-note free-collaboration, where they just had to write a specific program. That same student honest-to-God tried to pay another teacher to write it for her! LOL

I would definitely not hate a real advanced programming course, but the closest I can find is to sign up for an online Bachelor's degree program, then have to sift through 3 years of nonsense just to get to the good stuff. And for all I know, it might be a lot more remedial than I need, and I'd have to continue on to a Master's. I don't need to know it in 6 years, though, I'd rather just do another online tutorial and be done with it :-/