Few days back I wrote about the PLESK compromised servers in www.my-audit.gr, at that time I made a script to perform manual checks for our clients in our IP ranges. The script was slow and it was taking a lot of time to produce actual results at first, then I remembered about nmap scripting language (NSE). I had never used it before but it seems rather easy to make a simple script, so after a couple of minutes I came up with the following script:
1: description = [[
2: Looks for signature of PLESK servers that were compromised earlier in 2012.
3:
4: The script checks the existence of enterprise/control/psa/engine.php and
5: /enterprise/control/ctrl.php3 files that are not part of plesk distribution.
6: The files were added in most servers during the first 3 months of 2012
7: after a global scale attack on PLESK hosting servers.
8: More at: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/ ,
9: http://forum.parallels.com/showthread.php?t=258101 and
10: http://0entropy.blogspot.com/2012_03_01_archive.html
11: ]]
12:
13: ---
14: -- the result will be something like the following
15: -- Interesting ports on somehost.someserver.com (xxx.xxx.193.64):
16: -- PORT STATE SERVICE
17: -- 8443/tcp open https-alt
18: -- |_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
19: ---
20:
21: author = "Nicolas Krassas"
22: license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
23: categories = {"malware","discovery","safe"}
24:
25: require "http"
26: require "shortport"
27: require "stdnse"
28:
29: -- This script will check on port 8443 only
30: portrule = function(host, port)
31: local svc = { std = { ["https-alt"] = 1 } }
32: if port.protocol ~= 'tcp' or not svc.std[port.service] then
33: return false
34: end
35: return true
36: end
37:
38: -- Execute the check
39: action = function(host, port)
40:
41: -- Perform a GET request for v2 backdoor, this is the most common currently.
42: result = http.get_url("https://" .. host.ip .. ":" .. port.number .. "/enterprise/control/psa/engine.php")
43:
44: if(not(result)) then
45: return stdnse.format_output(false, "Couldn't perform GET request")
46: end
47:
48: if(result.status == 200) then
49: string = ("PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/");
50: return string
51: end
52:
53: -- Perform a GET request for v1 backdoor
54: result = http.get_url("https://" .. host.ip .. ":" .. port.number .. "/enterprise/control/ctrl.php3")
55:
56: if(not(result)) then
57: return stdnse.format_output(false, "Couldn't perform GET request")
58: end
59:
60: if(result.status == 200) then
61: string = ("PLESK infected v1, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/");
62: return string
63: end
64: end
a sample output from the script,
root@host:~# nmap --script http-plesk-backdoor xxx.xxx.xxx.xxx
Starting Nmap 5.00 ( http://nmap.org ) at 2012-05-09 14:20 EEST
Interesting ports on someserver.com (xxx.xxx.xxx.xxx):
Not shown: 979 closed ports
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
25/tcp open smtp
53/tcp open domain
80/tcp open http
106/tcp open pop3pw
110/tcp open pop3
135/tcp filtered msrpc
139/tcp filtered netbios-ssn
143/tcp open imap
443/tcp open https
445/tcp filtered microsoft-ds
465/tcp open smtps
587/tcp open submission
646/tcp filtered ldp
993/tcp open imaps
995/tcp open pop3s
1025/tcp filtered NFS-or-IIS
2000/tcp filtered callbook
3306/tcp open mysql
8443/tcp open https-alt
|_ http-plesk-backdoor: PLESK infected v1, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
Nmap done: 1 IP address (1 host up) scanned in 2.98 seconds
and scanning a larger range,
root@host:~# nmap --script http-plesk-backdoor xxx.xxx.193.0/24 -p 8443
--snip--
Interesting ports on srv1.someserver.com (xxx.xxx.193.61):
PORT STATE SERVICE
8443/tcp open https-alt
Interesting ports on srv2.someserver.com (xxx.xxx.193.62):
PORT STATE SERVICE
8443/tcp open https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
Interesting ports on srv3.someserver.com (xxx.xxx.193.63):
PORT STATE SERVICE
8443/tcp open https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
Interesting ports on srv4.someserver.com (xxx.xxx.193.64):
PORT STATE SERVICE
8443/tcp open https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
--snip--
The script can be found here, http://chaos.deventum.com/research/nse/http-plesk-backdoor.nse