summaryrefslogtreecommitdiffstats
path: root/scripts/http-php-version.nse
blob: c1767ee43af42b33fa5bda066d58aa0afe036c7c (plain)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
local http = require "http"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"

local openssl = stdnse.silent_require "openssl"

description = [[
Attempts to retrieve the PHP version from a web server. PHP has a number
of magic queries that return images or text that can vary with the PHP
version. This script uses the following queries:
* <code>/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42</code>: gets a GIF logo, which changes on April Fool's Day.
* <code>/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000</code>: gets an HTML credits page.

A list of magic queries is at http://www.0php.com/php_easter_egg.php.
The script also checks if any header field value starts with
<code>"PHP"</code> and reports that value if found.

PHP versions after 5.5.0 do not respond to these queries.

Link:
* http://phpsadness.com/sad/11
]]

---
-- @output
-- PORT   STATE SERVICE REASON
-- 80/tcp open  http    syn-ack
-- | http-php-version: Versions from logo query (less accurate): 4.3.11, 4.4.0 - 4.4.9, 5.0.4 - 5.0.5, 5.1.0 - 5.1.2
-- | Versions from credits query (more accurate): 5.0.5
-- |_Version from header x-powered-by: PHP/5.0.5

-- 2016-02-05: Updated versions based on scans of Internet hosts. Table is
--             likely complete, since new PHP versions are not vulnerable.
-- 08/10/2010:
--   * Added a check on the http status when querying the server:
--     if the http code is 200 (ok), proceed. (thanks to Tom Sellers who has reported this lack of check)

author = {"Ange Gutek", "Rob Nicholls"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}


portrule = shortport.http

-- These are the magic queries that return fingerprintable data.
local LOGO_QUERY = "/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42"
local CREDITS_QUERY = "/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000"

-- For PHP 5.x hashes up to 5.2.14 and 5.3.3 see:
-- http://seclists.org/nmap-dev/2010/q4/518

local LOGO_HASHES = {
  -- Bunny (Carmella)
  ["37e194b799d4aaff10e39c4e3b2679a2"] = {"5.0.0 - 5.0.3"},
  -- Black Scottish Terrier (Scotch)
  ["4b2c92409cf0bcf465d199e93a15ac3f"] = {"4.3.11", "4.4.0 - 4.4.9", "5.0.4 - 5.0.5", "5.1.0 - 5.1.2"},
  -- Colored
  ["50caaf268b4f3d260d720a1a29c5fe21"] = {"5.1.3 - 5.1.6", "5.2.0 - 5.2.17"},
  -- PHP Code Guy With Breadsticks (Thies C. Arntzen)
  ["85be3b4be7bfe839cbb3b4f2d30ff983"] = {"4.0.0 - 4.2.3"},
  -- Brown Dog In Grass (Nadia)
  ["a57bd73e27be03a62dd6b3e1b537a72c"] = {"4.3.0 - 4.3.11"},
  -- Elephant
  ["fb3bbd9ccc4b3d9e0b3be89c5ff98a14"] = {"5.3.0 - 5.3.29", "5.4.0 - 5.4.45"},
}

local CREDITS_HASHES = {
  ["744aecef04f9ed1bc39ae773c40017d1"] = {"4.0.1pl2", "4.1.0 - 4.1.2", "4.2.2"},
  ["4ba58b973ecde12dafbbd40b54afac43"] = {"4.1.1 OpenVMS"},
  ["8bc001f58bf6c17a67e1ca288cb459cc"] = {"4.2.0 - 4.2.2"},
  ["3422eded2fcceb3c89cabb5156b5d4e2"] = {"4.2.3"},
  ["1e04761e912831dd29b7a98785e7ac61"] = {"4.3.0"},
  ["1e04761e912831dd29b7a98785e7ac61"] = {"4.3.1"},
  ["65eaaaa6c5fdc950e820f9addd514b8b"] = {"4.3.1 Mandrake Linux"},
  ["8a8b4a419103078d82707cf68226a482"] = {"4.3.2"},
  ["22d03c3c0a9cff6d760a4ba63909faea"] = {"4.3.2"}, -- entity encoded "'"
  ["8a4a61f60025b43f11a7c998f02b1902"] = {"4.3.3 - 4.3.5"},
  ["39eda6dfead77a33cc6c63b5eaeda244"] = {"4.3.3 - 4.3.5"}, -- entity encoded "'"
  ["913ec921cf487109084a518f91e70859"] = {"4.3.6 - 4.3.8"},
  ["884ba1f11e0e956c7c3ba64e5e33ee9f"] = {"4.3.6 - 4.3.8"}, -- entity encoded
  ["c5fa6aec2cf0172a5a1df7082335cf9e"] = {"4.3.8 Mandrake Linux"},
  ["8fbf48d5a2a64065fc26db3e890b9871"] = {"4.3.9 - 4.3.11"},
  ["f9b56b361fafd28b668cc3498425a23b"] = {"4.3.9 - 4.3.11"}, -- entity encoded "'"
  ["ddf16ec67e070ec6247ec1908c52377e"] = {"4.4.0"},
  ["3d7612c9927b4c5cfff43efd27b44124"] = {"4.4.0"}, -- entity encoded "'"
  ["55bc081f2d460b8e6eb326a953c0e71e"] = {"4.4.1"},
  ["bed7ceff09e9666d96fdf3518af78e0e"] = {"4.4.2 - 4.4.4"},
  ["692a87ca2c51523c17f597253653c777"] = {"4.4.5 - 4.4.7"},
  ["50ac182f03fc56a719a41fc1786d937d"] = {"4.4.8 - 4.4.9"},
  ["3c31e4674f42a49108b5300f8e73be26"] = {"5.0.0 - 5.0.5"},
  ["e54dbf41d985bfbfa316dba207ad6bce"] = {"5.0.0"},
  ["6be3565cdd38e717e4eb96868d9be141"] = {"5.0.5"},
  ["b7cf53972b35b5d57f12c9d857b6b507"] = {"5.0.5 ActiveScript"},
  ["5518a02af41478cfc492c930ace45ae5"] = {"5.1.0 - 5.1.1"},
  ["6cb0a5ba2d88f9d6c5c9e144dd5941a6"] = {"5.1.2"},
  ["82fa2d6aa15f971f7dadefe4f2ac20e3"] = {"5.1.3 - 5.1.6"},
  ["6a1c211f27330f1ab602c7c574f3a279"] = {"5.2.0"},
  ["d3894e19233d979db07d623f608b6ece"] = {"5.2.1"},
  ["56f9383587ebcc94558e11ec08584f05"] = {"5.2.2"},
  ["c37c96e8728dc959c55219d47f2d543f"] = {"5.2.3 - 5.2.5", "5.2.6RC3"},
  ["1776a7c1b3255b07c6b9f43b9f50f05e"] = {"5.2.6"},
  ["1ffc970c5eae684bebc0e0133c4e1f01"] = {"5.2.7 - 5.2.8"},
  ["54f426521bf61f2d95c8bfaa13857c51"] = {"5.2.9 - 5.2.14"},
  ["adb361b9255c1e5275e5bd6e2907c5fb"] = {"5.2.15 - 5.2.17"},
  ["db23b07a9b426d0d033565b878b1e384"] = {"5.3.0"},
  ["a4c057b11fa0fba98c8e26cd7bb762a8"] = {"5.3.1 - 5.3.2"},
  ["b34501471d51cebafacdd45bf2cd545d"] = {"5.3.3"},
  ["e3b18899d0ffdf8322ed18d7bce3c9a0"] = {"5.3.4 - 5.3.5"},
  ["2e7f5372931a7f6f86786e95871ac947"] = {"5.3.6"},
  ["f1f1f60ac0dcd700a1ad30aa81175d34"] = {"5.3.7 - 5.3.8"},
  ["23f183b78eb4e3ba8b3df13f0a15e5de"] = {"5.3.9 - 5.3.29"},
  ["85da0a620fabe694dab1d55cbf1e24c3"] = {"5.4.0 - 5.4.14"},
  ["ebf6d0333d67af5f80077438c45c8eaa"] = {"5.4.15 - 5.4.45"},
}

action = function(host, port)
  local response
  local logo_versions, credits_versions
  local logo_hash, credits_hash
  local header_name, header_value
  local lines

  -- 1st pass : the "special" PHP-logo test
  response = http.get(host, port, LOGO_QUERY)
  if response.body and response.status == 200 then
    logo_hash = stdnse.tohex(openssl.md5(response.body))
    logo_versions = LOGO_HASHES[logo_hash]
  end

  -- 2nd pass : the PHP-credits test
  response = http.get(host, port, CREDITS_QUERY)
  if response.body and response.status == 200 then
    credits_hash = stdnse.tohex(openssl.md5(response.body))
    credits_versions = CREDITS_HASHES[credits_hash]
  end

  for name, value in pairs(response.header) do
    if string.match(value, "^PHP/") then
      header_name = name
      header_value = value
      break
    end
  end

  lines = {}
  if logo_versions then
    lines[#lines + 1] = "Versions from logo query (less accurate): " .. table.concat(logo_versions, ", ")
  elseif logo_hash and nmap.verbosity() >= 2 then
    lines[#lines + 1] = "Logo query returned unknown hash " .. logo_hash
  end
  if credits_versions then
    lines[#lines + 1] = "Versions from credits query (more accurate): " .. table.concat(credits_versions, ", ")
  elseif credits_hash and nmap.verbosity() >= 2 then
    lines[#lines + 1] = "Credits query returned unknown hash " .. credits_hash
  end
  if header_name and header_value then
    lines[#lines + 1] = "Version from header " .. header_name .. ": " .. header_value
  end

  if #lines > 0 then
    return table.concat(lines, "\n")
  end
end