← Back to all posts
WEB Vulnerability Reproduction and Analysis7 min read

Multiple Methods for Evading Webshell Detection

An exploration of common PHP webshell detection-evasion techniques, including string transformations, function and class features, arrays, variable variables, special-character obfuscation, and letterless payloads.

Read in Chinese→

0x00 Prerequisites

  • It is the last day of 2020. I did not manage to finish writing anything this month, so this is something I had in reserve. I have been ill and genuinely feel so awful that I cannot do anything—I cannot stand, sit, or even lie down comfortably every day… Sigh… In short, your health really is important. Do not ruin it!!!
  • Webshells are extremely important in web security. It is frustrating when the shell you have obtained gets detected, so I decided to research my own detection-evasive webshells. After all, other people’s are not as useful as your own, and anything shared publicly gets detected in no time.
  • This article introduces some commonly used techniques for evading webshell detection.

0x01 Detection

  • WAFs generally maintain a rule base containing functions, methods, and other features commonly used by webshells. They determine whether something is a webshell by matching it against this rule base.
  • An alert is triggered when a corresponding signature is matched. However, rule matching inevitably produces false positives, and constant WAF alerts are also annoying. WAFs therefore generally prioritize stability and relax their rules somewhat, which provides the basis for bypasses.

My first choice for scanning software is D-Shield.

“D-Shield Firewall” is proactive defense software designed specifically for IIS. It protects both websites and servers from intrusion. It was designed around the principle that, while websites continue to operate normally, fewer features make a server more secure. It restricts common intrusion methods to make servers safer!

0x02 PHP One-Liners

This experiment mainly focuses on evading detection with PHP one-liners.

First, let us look at the most common PHP one-liner.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

Breaking it down:

  • [sample omitted; see Chinese original] is the function that executes commands.
  • [sample omitted; see Chinese original] is the function that receives data, and a is the parameter being passed.
  • The [sample omitted; see Chinese original] function executes the received data as PHP code.
  • This is a one-line webshell.

I prefer the [sample omitted; see Chinese original] function.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

The reason:

There are differences between PHP 5 and PHP 7.

Function Description
eval Available in PHP 4, PHP 5, and PHP 7+. It accepts one argument and executes the string as PHP code.
assert Available in PHP 4, PHP 5, and versions earlier than PHP 7.2. It generally accepts one argument, but can accept two arguments starting with PHP 5.4.8.

In PHP 5, [sample omitted; see Chinese original] is a function, so we can use a method such as [sample omitted; see Chinese original] to execute arbitrary code dynamically.

In PHP 7, [sample omitted; see Chinese original] is no longer a function. It has become a language construct, similar to [sample omitted; see Chinese original], and can no longer be used as a function name to execute code dynamically.

Similarity: Both can execute PHP statements. However, [sample omitted; see Chinese original] has stricter syntax and must receive valid PHP code, whereas [sample omitted; see Chinese original] is less strict and only needs a PHP expression.

Put simply:

[sample omitted; see Chinese original] is a language construct rather than a function, so it cannot be invoked as a variable function.

[sample omitted; see Chinese original] can be invoked as a variable function, including through various callback functions, which makes it much more convenient.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

0x03 The assert Function

[sample omitted; see Chinese original] is an assertion function. If the condition evaluated by [sample omitted; see Chinese original] is false, it issues a warning but continues executing subsequent code. This is very useful for debugging, especially when callback functions can be used. If user-supplied data is not filtered rigorously, [sample omitted; see Chinese original] can be even more dangerous than [sample omitted; see Chinese original].

image-20201231133401683

Different programming languages require different approaches. I will use PHP as an example. The overall idea is to separate the relationship between code and functions.

There are roughly several approaches:

  • String transformations (concatenation, encoding, and so on…)
  • Function features
  • Class features
  • Combined detection evasion
  • Creative ideas

0x03 String Transformations

Simple string transformations alone still look suspicious, so they need to be combined with other techniques.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20201231133428867

0x04 Function Features

The function-based techniques I know include:

  • Bypassing with custom functions
  • Modified callbacks
  • Arrays
  • Variable variables

Bypassing with Custom Functions

A purely custom function can still bypass detection.

Here is a detection-evasive webshell for everyone. It will probably stop working in a few days.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20201231133441831

Callback Functions + Combined Bypass

This is somewhat difficult now. I found the following ones.

Most of them have already been blacklisted… Using any one of them by itself will get detected.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

  • Therefore, they can only be combined with the techniques above. Here is another detection-evasive webshell.
  • This one simply defines a function and adds some basic concatenation.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20201231133455779

Array Bypass

Two-Dimensional Arrays

The idea is to place the one-line webshell to be executed inside an array, thereby achieving a bypass.

As usual, here is the detection-evasive webshell.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20201231133508080

Variable Variables

PHP has a type of variable called a variable variable. This is not a basic variable type. A variable variable means that the value of an ordinary variable can be used as the name of another variable. This may sound somewhat abstract. We can use an example to demonstrate the definition and practical use of variable variables.

For example:

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

In the code above, the first line defines an ordinary variable named a whose value is hello.

The second line uses the value of variable a to define another variable. This variable is named hello, which is the value of a, and its value is world.

The output of this variable is world.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20200407220547482

That does not work; there are already some problems with it. The [sample omitted; see Chinese original] function therefore needs further processing and must be combined with the special-character interference described below.

0x05 Special-Character Interference

  • The characters must interfere with the antivirus software’s regular-expression matching while still allowing the code to execute.
  • You can fuzz this yourself.
  • This generally involves various carriage returns, line feeds, nulls, and whitespace characters.
  • I tried it here and succeeded by combining it with the variable variables described above.

Here is a detection-evasive webshell:

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

0x06 Bypassing with Classes

I have noticed that many people now use classes. D-Shield seems to flag this approach the least severely. Naturally, using classes also involves magic methods.

Here is a simple detection-evasive webshell constructed with a class.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

image-20201231133525255

0x07 Another Letterless Webshell

The main idea is:

  • There are no letters; put simply, the letters are replaced.
  • Various operations, such as XOR, are used to assemble the desired function.
  • Ultimately, any character from a to z can be constructed.
  • PHP’s ability to execute functions dynamically is then used.
  • A function name such as [sample omitted; see Chinese original] is concatenated and executed dynamically.

This is based on P Niu’s explanation, which is already very clear. Anyone interested can take a look.

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

Here is a challenge I solved previously. It uses a similar approach and is very interesting.

Executable sample omitted in the English preview. Refer to the original Chinese article for the archived code.

0x08 Summary

  • Based on this exploration, evading detection with one-liners is relatively simple. A single method may not work very well, but combining several methods is quite convenient.
  • In my opinion, the key to PHP detection evasion lies in PHP’s support for dynamic function execution, which offers many possible approaches.
  • Next, I will research traffic-based detection evasion and evasion for China Chopper.