# Sucuri Blog **[blog.sucuri.net/2021/02/whitespace-steganography-conceals-web-shell-in-php-malware.html](https://blog.sucuri.net/2021/02/whitespace-steganography-conceals-web-shell-in-php-malware.html)** Denis Sinegubko February 2, 2021 Last November, we wrote about how attackers are using JavaScript injections to load malicious code from legitimate CSS files. At first glance, these injections didn’t appear to contain anything except for some benign CSS rules. A more thorough analysis of the .CSS file revealed 56,964 seemingly empty lines containing combinations of invisible tab (0x09), space (0x20), and line feed (0x0A) characters, which were converted to binary representation of characters and then to the text of an executable JavaScript code. It didn’t take long before we found the same approach used in PHP malware. Here’s what [our malware analyst Liam Smith discovered while recently working on a site containing](https://twitter.com/liamsmith86) multiple backdoors and webshells uploaded by hackers. ## Suspicious license.php file One of the files Liam found looked a bit strange: system/license.php. As the filename implies, it contains text for a license agreement — more specifically, text for [GNU General Public License version 3.](https://www.gnu.org/licenses/gpl-3.0.en.html) The license text is placed inside a multi-line PHP comment. However, on line 134 we see a gap between two comments that contains executable PHP code. ----- PHP code inside license.php Hiding malicious code between comment blocks is a common obfuscation technique used by hackers. The code is obviously malicious but, after first glance, it was not clear whether the malware was complete or had any other parts in that file. It’s easy to notice that it tries to read itself and do something with its contents using **file_get_contents(basename($_SERVER[‘PHP_SELF’]))). A quick visual inspection of the** file, however, didn’t reveal any other sections that can be converted into working PHP code. ## Analysis of the Visible Malicious Code To understand what exactly the malicious code does, we analyzed each statement piece by piece. The first clause splits the file contents into sections divided by semicolon characters and assigns the last section to the $cache variable. In plain words, this code works with the part of the file found after the last “;”. It turns out that the final semicolon in the file is also the last character of the license agreement: “But first, please read ;”. In the original license agreement the last character is a period, indicating that** the file was intentionally modified by the attacker for this clause. There is nothing clearly visible after this last semicolon. To understand what’s being done with the trailing part of the file, we need to analyze the next section of malware clauses. ## Whitespace Decoder ----- ``` for($i 0;$i