What Is So Wrong With Extract()

What is so wrong with extract()?

I find that it is only bad practice in that it can lead to a number of variables which future maintainers (or yourself in a few weeks) have no idea where they're coming from. Consider this scenario:

extract($someArray); // could be $_POST or anything

/* snip a dozen or more lines */

echo $someVariable;

Where did $someVariable come from? How can anyone tell?

I don't see the problem in accessing the variables from within the array they started in, so you'd really need to present a good case for using extract() for me to think it's worth it. If you're really concerned about typing out some extra characters then just do this:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

I think the comments here on the security aspects of it are overblown somewhat. The function can take a second parameter that actually gives you fairly good control over the newly created variables, including not overwriting any existing variables (EXTR_SKIP), ONLY overwriting existing variables (so you can create a whitelist) (EXTR_IF_EXISTS), or adding prefixes to the variables (EXTR_PREFIX_ALL).

Is it bad for performance to extract variables from an array?

Update:

As the commenter below noted and as I am now keenly aware years later - php variables are copy on write. Extracting in the global scope will however keep the variables from being garbage collected. So as I said before, "consider your scope"


Depends on the size of the array and the scope to which your extracting it, say you extract a huge array to the global namespace, I could see that having an effect, as you will have all that data in memory twice - I believe though it may do some fun internal stuff which PHP is known to do to limit that -

but say you did

function bob(){
extract( array( 'a' => 'woo', 'b' =>'fun', 'c' => 'array' ) );
}

its going to have no real lasting effect.

Long story short, just consider what you're doing, why your doing it, and the scope.

How to securely create PHP variables with extract

The best option is to not use extract() at all. It's a bad design decision from the days when PHP was the equivalent of wet toilet paper for writing secure code.

It may be painful, but it is far better to write out a long sequence of:

$var1 = $_POST['var1'];
$var2 = $_POST['var2'];
etc...

or simply use $_POST['var1'] and company everywhere in your code.

As soon as you start using extract, you're giving malicious users a potential way into your code, no matter how much time/effort you put into it. You don't drill a hole through a bank vault door because it's too annoying to have to open the door each time to let some money out. Once there's a hole, it will be exploited.

problem with using extract php function?

Maybe something like this is better:

function check($user_id, $topic_id){
$query = mysql_query("SELECT user_id, topic_id FROM sa where topic_id='$topic_id' and user_id='$user_id'");
if (mysql_num_rows($query)==1){
return array('error'=>'you have already voted');
}
else {
$against = ' <li>
<button type="submit" value="Actions" class="against" title="against">
<i></i><span>Against</span></button>
</li>';

$support ='<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>';
return compact('support', 'against');
}
}

$result = check($_SESSION['user_id'], $topicId);

if(isset($result['error'])) {
echo $result['error'];
}
else {
echo $result['against'];
echo $result['support'];
}

You could also consider to use exceptions.

How to demonstrate an exploit of extract($_POST)?

For assessing "might" try this:

File:htdocs/mix/extraction.php

<?php
extract($_GET);
var_dump($_SERVER);//after extract
?>

and call it like that:

http://localhost/mix/extraction.php?_SERVER=test

After the extract on my Xampp the output looks something like that:

string(4) "test"

If any one knows anything about your variable naming and you use extract on $_POST or $_GET globals, then you have a serious problem.
With a bit of time and work it would be possible to find out some namings by try and error.

Without knowing your source an intruder could try to hijack any global variabl like $_SESSION (but here it will only take any effect if you do the session_start(); before the extract($_GET), $_COOKIE or $_SERVER and even set specific values for them like that:

//localhost/mix/extraction.php?_SERVER[HTTP_USER_AGENT]=Iphone

If you use extract like that:

extract($var,EXTR_SKIP);

extract($var,EXTR_PREFIX_SAME,'prefix');

extract($var,EXTR_PREFIX_ALL,'prefix');

then you will be perfectly safe.

PHP: is there a safe way to extract($_POST)

One more cautious way of extracting all input fields at once is:

extract( $_POST, EXTR_OVERWRITE, "form_" );

This way all your input variables will be called $form_foo and $form_bar at least. Avoid doing that in the global scope - not because global is evil, but because nobody ever cleans up there.

However, since mostly you do that in a localized scope, you can as well apply htmlentities if for example you need all fields just for output:

extract(array_map("htmlspecialchars", $_POST), EXTR_OVERWRITE, "form_");

Beautiful Soup extract() problem

this seems to actually not be a BeautifulSoup problem. The problem lies with the fact that the XML that's being generated is not being recognized by the application (Tabeleau) as valid xml.

Why regex extract return wrong value in scala

findFirstIn() returns the first sub-string that matches the pattern. If you don't want a sub-string, but just to test for a match, then that's not the tool you want to use.

scala> "ABCE1234" matches "[A-Z]{2,3}[0-9]{4}"
res5: Boolean = false

scala> "ABC1234" matches "[A-Z]{2,3}[0-9]{4}"
res6: Boolean = true

If you want to extract a matching word from a longer string then you need to incorporate the word boundaries into your pattern.

scala> val pattern = "\\b[A-Z]{2,3}[0-9]{4}\\b".r
pattern: scala.util.matching.Regex = \b[A-Z]{2,3}[0-9]{4}\b

scala> val extractedData = pattern.findFirstIn("find ABCD1234")
extractedData: Option[String] = None

scala> val extractedData = pattern.findFirstIn("find ABC1234")
extractedData: Option[String] = Some(ABC1234)


Related Topics



Leave a reply



Submit