PHP create_function, function without semicolon? - php

basically, what i want to know is, for the second parameter in the create_function function, is there anyway to pass a string without a semicolon? or will it not work.
example:
taken from php.net
create_function('$a,$b', 'return "CRCs: " . crc32($a) . " , ".crc32(b);'),
notice that there is a semicolon in the string. is there any possible way someone can enter a function without a semicolon that will still run/evaluate?

With create_function() you're creating an anonymous function. The second parameter is a string that is the code of the function (like any other function you'd write). It doesn't have to end in a semicolon, for example:
$coolfunction = create_function('$thing', 'if ($thing > 0) {return "Yes"; } else { return "no!"; }');
echo $coolfunction(1) . ' and ' . $coolfunction(-1);
Ends in a '}' and prints out: Yes and no!

No it is not possible. PHP is semicolon-sensitive, that you must use it to terminate every statements before right braces. I even tried regular function like this:
function f() {
return 1
}
and it spitted out a syntax error, unlike in JavaScript.

You should always sanitize any user input before using it.
I suggest that you look for the semicolon in the user input, if it is missing, append it.
If the user can enter anything here you still have a problem if he enters an invalid function name or just rubbish.
You can validate with preg_match() (although I'm not an expert on preg so I will let someone else help you out there).

First, why do you need that ? That's a really dirty way to create a function. Hope because you want to make a interface where people can directly create a function (and this will be only for you or it'll be a big security issue). I don't really get how you want to use that.
Anyway, for you question, you don't have to care if it's working or not. I mean, just test if it's working, if not just put by yourself a semicolon. It's just a simply test on a string.

Related

Concatenate functions in PHP to use in an URL

I am penetration testing a web application and I need to concatenate two functions in one URL. (Yes, I already checked this one and this one)
I am going to take the exact same code, because I did not understand why there is no proper answer to a legit question like this one. (psst, it's not about a backdoor or something)
<?php
if(isset($_GET['function'])){
$_GET['function']();
}
?>
Is there any possibility to create something like this?
http://localhost/?function=shell_exec('ls') AND phpinfo
Thank you for your help and I hope this time someone will take a legit question seriously instead of downvoting it to hell for no logical reason.
There's two problems here, I'll answer the question first.
Why not make it an array?
Url:
http://localhost/?function[]=phpinfo&function[]=bob
Code:
$functions = (array)$_GET['function'];
foreach($functions as $function) {
$function();
}
The second problem is you aren't easily going to be able to pass in parameters as you have it above. You might need to do a little bit of regex first, but then you're on thin ice.
This is a huge guess, but something like:
$matches = [];
preg_match('/(\w+)\(('?(\w+)'?,?)+\)/', $functions, $matches);
You should then be able extract the function name and parameters (as long as they're strings) and call the function with the parameters. But that regex is obviously dodgy as anything :/
That looks extremely dangerous. You can pass a string separated with a semicolon for each function, like this
:
http://localhost/?function=shell_exec('ls');phpinfo
So your actual code would become:
if(isset($_GET['function'])){
$functions = explode(';',$_GET['function']);
foreach($functions as $function){
$function();
}
}
You may also use the eval function:
http://localhost/?function=?eval=shell_exec('ls');phpinfo();
followed by eval($_GET['eval']);, as suggested in the comments below.

Deleting part of string in php using str_replace

I have a little issue with deleting a part of string using php.
Let me get you a little bit into problem, I have vlariable "column1text" in which is text string endered into < textarea >, but that does not matter. I want to remove all HTML tags from this string since they are doing problems sometimes. For example: When this string contains < /body > or < /table > it will do a lot of unwanted mess. So I want to get these tags away.
I am using $column1text = str_replace("TEXT TO REMOVE", "", $column1text); and it works, but I want to make function for it (optionaly if you know easier way, just tell me, I'll be glad).
I am using this function:
function remove($removetext)
{
$column1text = str_replace($removetext, "", $column1text);
}
And I am using it like this:
remove("TEXT TO REMOVE");
What am I doing wrong? (I am sure it's something pretty silly, but I cannot find it!)
P.S. I am totally sorry about my English, it must sound stupid, but I had no other idea than asking you.
You can either pass in $column1text as reference, or have your function returns the modified text (which I prefer)
function remove($column1text, $removetext) {
return str_replace($removetext, "", $column1text);
}
$column1text = remove($column1text, '<span>');
You are passing by value, when you actually need to be passing by reference. If you don't know what the difference is I suggest reading up a little on it.
Link
edit:
In a nutshell, whenever you pass a function a parameter, that function makes a copy of whatever it was passed, so when that parameter is manipulated in the function, it manipulates the copy and not the passed object itself.
When a function has a parameter passed by reference, then it actually has access to the object that was passed itself. That means anything you do to manipulate that object also affects the object outside of the function (since its not just a copy of it you are working with).
You need to tell interpreter that you want to use global variable, because now it sees it as local variable (within your function). To do this you just need to use global keyword:
function remove($removetext) {
global $column1text;
$column1text = str_replace($removetext, "", $column1text);
}
you can read more about it here http://php.net/manual/en/language.variables.scope.php

Fatal error: Can't use function return value in write context

I have a pretty nasty error I can't get rid of. Here's the function causing the issue:
function get_info_by_WatIAM($WatIAM, $info) {
$users_info = array();
exec("uwdir -v userid={$WatIAM}", $users_info);
foreach ($users_info as $user_info) {
$exploded_info = explode(":", $user_info);
if (isset($exploded_info[1])){
$infoArray[$exploded_info[0]] = $exploded_info[1];
}
}
return $infoArray[$info]; }
Here's what's calling the function:
} elseif ( empty(get_info_by_WatIAM($_POST['ownerId'])) ) { ...
I would really appreciate any suggestion. Thanks very much!
If the code doesn't make sense, here's a further explanation: exec uses a program that stores information on all the users in a school. These include things like faculty, name, userid, etc. The $_POST['ownerId'] is a username -- the idea is that, upon entering a username, all of the user's information is automatically filled in
You do not need empty around function calls, in fact empty only works with variables and not functions (as you see). You only need empty if you want to test a variable that may not be set for thruthiness. It is pointless around a function call, since that function call must exist. Instead simply use:
} else if (!get_info_by_WatIAM($_POST['ownerId'])) { ...
It does the same thing. For an in-depth explanation, read The Definitive Guide To PHP's isset And empty.
empty can only be used on variables, not on expressions (such as the result of calling a function). There's a warning on the documentation page:
Note:
empty() only checks variables as anything else will result in a parse
error. In other words, the following will not work: empty(trim($name)).
Just one of PHP's best-left-alone quirks.
One workaround is to store the result in a variable and call empty on that, although it's clunky. In this specific case, you can also use
if (!get_info_by_WatIAM(...))
...although in general, if (empty($a)) and if(!$a) are not equivalent.
get the value of this
$a = get_info_by_WatIAM($_POST['ownerId'])
then chack
empty($a)
it will work

str_replace: Replace string with a function

Just a simple question. I have a contact form stored in a function because it's just easier to call it on the pages I want it to have.
Now to extend usability, I want to search for {contactform} using str_replace.
Example:
function contactform(){
// bunch of inputs
}
$wysiwyg = str_replace('{contactform}', contactform(), $wysiwyg);
So basically, if {contactform} is found. Replace it with the output of contactform.
Now I know that I can run the function before the replace and store its output in a variable, and then replace it with that same variable. But I'm interested to know if there is a better method than the one I have in mind.
Thanks
To answer your question, you could use PCRE and preg_replace_callback and then either modify your contactform() function or create a wrapper that accepts the matches.
I think your idea of running the function once and storing it in a variable makes more sense though.
Your method is fine, I would set it as a $var if you are planning to use the contents of contactform() more than once.
It might pay to use http://php.net/strpos to check if {contact_form} exists before running the str_replace function.
You could try both ways, and if your server support it, benchmark:
<?php echo 'Memory Usage: '. (!function_exists('memory_get_usage') ? '0' : round(memory_get_usage()/1024/1024, 2)) .'MB'; ?>
you may want to have a look at php's call_user_func() more information here http://php.net/call_user_func
$wysiwyg = 'Some string and {contactform}';
$find = '{contactform}';
strpos($wysiwyg, $find) ? call_user_func($find) : '';
Yes, there is: Write one yourself. (Unless there already is one, which is always hard to be sure in PHP; see my next point.)
Ah, there it is: preg_replace_callback(). Of course, it's one of the three regex libraries and as such, does not do simple string manipulation.
Anyway, my point is: Do not follow PHP's [non-]design guidelines. Write your own multibyte-safe string substitution function with a callback, and do not use call_user_func().

PHP: include() bug, or user error? (Passed filename in IF statement)

Alright so I've already created a PHP bug about this but it was marked as bogus, but I can't help but to believe they didn't read it carefully...
Link to Bug #54042
The error is caused by using an include() statement in an IF statement, making the statement believe it's been passed an empty string.
Reviewing the bug will explain everything, including a test script.
Is it a bug, or am I missing something "feature"-wise? This is weird seeing as how assigning the output of include to a variable and then testing that value works just fine (which would be the workaround).
Well, the documentation says:
Because include() is a special language construct, parentheses are not needed around its argument. Take care when comparing return value.
<?php
// won't work, evaluated as include(('vars.php') == 'OK'), i.e. include('')
if (include('vars.php') == 'OK') {
echo 'OK';
}
// works
if ((include 'vars.php') == 'OK') {
echo 'OK';
}
?>
So this behaviour is already known and not considered as a bug. You even have an explanation why it works this way:
include does not need parenthesis, so PHP does not really whether you want to do:
include('vars.php')
or
include(('vars.php') == 'OK')
It seems that it is implemented to interpet it as the latter (something like the longest possible match).
Same goes for
$v = include('foo') . 'bar';
which PHP interprets as
$v = include(('foo') . 'bar');
and tries to load foobar.
But the solution is also given: Wrap the whole include statement into parenthesis, then there is only one way how PHP can interpret the call:
$v = (include ('foo')) . 'bar';
(Maybe) off topic: You will find similar "issues" in other parts of PHP. Take variable variables:
$obj->$foo['bar'];
PHP does not know whether you want to access the bar element of the array $foo and use this value as property name:
$obj->{$foo['bar']};
or if you want to access the bar element of $obj->$foo:
{$obj->$foo}['bar'];
In all these cases, there is a default behaviour of the parser. The developers decided for one possibility because they had to. It might not be what you expect, but if you know it, you can deal with it.
This behaviour cannot simply be changed as it might break code that relies on this behaviour.

Categories