peplum-nmap 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/examples/output.json +189 -0
- data/examples/rest/helpers.rb +44 -0
- data/examples/rest.rb +56 -0
- data/examples/rpc.rb +30 -0
- data/lib/peplum/nmap/native.rb +145 -0
- data/lib/peplum/nmap/version.rb +7 -0
- data/lib/peplum/nmap.rb +20 -0
- data/peplum-nmap.gemspec +24 -0
- metadata +80 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b8b8cbc832f6aba1427bc571e95d2dcf1bdcf1cca46373f1ea291bb43923586f
|
|
4
|
+
data.tar.gz: 06a2cbcae6e9d5bb77d4502eb4f29e82dd6425ec473e70a38fd39a2d9f8d8c5c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e5b9cabeeeda80a9f419ecfbdf0248edd4e43d90940aa099b023b0d510c04fd6fa568073704a24a4dc187d6ec4d0d5ba7929da5f939ef0ee20dd46efe8bb16be
|
|
7
|
+
data.tar.gz: 3fec8a89cf625873b304f3d487e6be807d3e33a18294552a41ee8a1107bbf79d6d62619a4488214de082154507bfe44231ae5b28f87cdc724d5e4226a342ed4b
|
data/bin/console
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "peplum/nmap"
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
require "irb"
|
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hosts": {
|
|
3
|
+
"192.168.1.1": {
|
|
4
|
+
"start_time": "2023-05-21 19:30:39 +0300",
|
|
5
|
+
"end_time": "2023-05-21 19:31:20 +0300",
|
|
6
|
+
"status": "up",
|
|
7
|
+
"addresses": [
|
|
8
|
+
"192.168.1.1"
|
|
9
|
+
],
|
|
10
|
+
"mac": null,
|
|
11
|
+
"vendor": null,
|
|
12
|
+
"ipv4": "192.168.1.1",
|
|
13
|
+
"ipv6": null,
|
|
14
|
+
"hostname": "mywebui.net",
|
|
15
|
+
"hostnames": [
|
|
16
|
+
"mywebui.net"
|
|
17
|
+
],
|
|
18
|
+
"os": null,
|
|
19
|
+
"uptime": null,
|
|
20
|
+
"ports": {
|
|
21
|
+
"53": {
|
|
22
|
+
"protocol": "tcp",
|
|
23
|
+
"state": "open",
|
|
24
|
+
"reason": "syn-ack",
|
|
25
|
+
"reason_ttl": "syn-ack",
|
|
26
|
+
"service": "dnsmasq 2.85",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"dns-nsid": {
|
|
29
|
+
"output": "\n bind.version: dnsmasq-2.85",
|
|
30
|
+
"data": {
|
|
31
|
+
"bind.version": "dnsmasq-2.85"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"80": {
|
|
37
|
+
"protocol": "tcp",
|
|
38
|
+
"state": "open",
|
|
39
|
+
"reason": "syn-ack",
|
|
40
|
+
"reason_ttl": "syn-ack",
|
|
41
|
+
"service": "http",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"http-server-header": {
|
|
44
|
+
"output": "httpd/2.7 (Netgear; D86)",
|
|
45
|
+
"data": [
|
|
46
|
+
"httpd/2.7 (Netgear; D86)"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"http-title": {
|
|
50
|
+
"output": "NETGEAR\nRequested resource was http://mywebui.net/index.html?sessionId=00000005%2DqJnmUh51Zh2tSmWlMkdD4dXOUxF7xn3",
|
|
51
|
+
"data": {
|
|
52
|
+
"title": "NETGEAR",
|
|
53
|
+
"redirect_url": "http://mywebui.net/index.html?sessionId=00000005%2DqJnmUh51Zh2tSmWlMkdD4dXOUxF7xn3"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"5510": {
|
|
59
|
+
"protocol": "tcp",
|
|
60
|
+
"state": "filtered",
|
|
61
|
+
"reason": "no-response",
|
|
62
|
+
"reason_ttl": "no-response",
|
|
63
|
+
"service": "secureidprop",
|
|
64
|
+
"scripts": {
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"192.168.1.43": {
|
|
70
|
+
"start_time": "2023-05-21 19:30:40 +0300",
|
|
71
|
+
"end_time": "2023-05-21 19:33:15 +0300",
|
|
72
|
+
"status": "up",
|
|
73
|
+
"addresses": [
|
|
74
|
+
"192.168.1.43"
|
|
75
|
+
],
|
|
76
|
+
"mac": null,
|
|
77
|
+
"vendor": null,
|
|
78
|
+
"ipv4": "192.168.1.43",
|
|
79
|
+
"ipv6": null,
|
|
80
|
+
"hostname": "deco_X60.net",
|
|
81
|
+
"hostnames": [
|
|
82
|
+
"deco_X60.net"
|
|
83
|
+
],
|
|
84
|
+
"os": null,
|
|
85
|
+
"uptime": null,
|
|
86
|
+
"ports": {
|
|
87
|
+
"80": {
|
|
88
|
+
"protocol": "tcp",
|
|
89
|
+
"state": "open",
|
|
90
|
+
"reason": "syn-ack",
|
|
91
|
+
"reason_ttl": "syn-ack",
|
|
92
|
+
"service": "http",
|
|
93
|
+
"scripts": {
|
|
94
|
+
"fingerprint-strings": {
|
|
95
|
+
"output": "\n FourOhFourRequest: \n HTTP/1.0 404 Not Found\n Connection: close\n Content-Type: text/html\n <h1>Not Found</h1>The requested URL /nice%20ports%2C/Tri%6Eity.txt%2ebak was not found on this server.\n GetRequest, HTTPOptions: \n HTTP/1.0 200 OK\n Connection: close\n ETag: \"86b-110-5ce64ee5\"\n Last-Modified: Thu, 23 May 2019 07:42:29 GMT\n Date: Sun, 21 May 2023 16:30:46 GMT\n X-Frame-Options: deny\n Content-Security-Policy: frame-ancestors 'none'\n Content-Type: text/html\n Content-Length: 272\n <?xml version=\"1.0\" encoding=\"utf-8\"?>\n <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n <html xmlns=\"http://www.w3.org/1999/xhtml\">\n <head>\n <meta http-equiv=\"refresh\" content=\"0; URL=/webpages/index.html\" />\n </head>\n </html>\n Help: \n HTTP/0.9 400 Bad Request\n Connection: Keep-Alive\n Keep-Alive: timeout=20\n Content-Type: text/html\n <h1>Bad Request</h1>\n RTSPRequest: \n HTTP/1.0 400 Bad Request\n Connection: Keep-Alive\n Keep-Alive: timeout=20\n Content-Type: text/html\n <h1>Bad Request</h1>",
|
|
96
|
+
"data": {
|
|
97
|
+
"FourOhFourRequest": "\n HTTP/1.0 404 Not Found\n Connection: close\n Content-Type: text/html\n <h1>Not Found</h1>The requested URL /nice%20ports%2C/Tri%6Eity.txt%2ebak was not found on this server.",
|
|
98
|
+
"GetRequest, HTTPOptions": "\n HTTP/1.0 200 OK\n Connection: close\n ETag: \"86b-110-5ce64ee5\"\n Last-Modified: Thu, 23 May 2019 07:42:29 GMT\n Date: Sun, 21 May 2023 16:30:46 GMT\n X-Frame-Options: deny\n Content-Security-Policy: frame-ancestors 'none'\n Content-Type: text/html\n Content-Length: 272\n <?xml version=\"1.0\" encoding=\"utf-8\"?>\n <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n <html xmlns=\"http://www.w3.org/1999/xhtml\">\n <head>\n <meta http-equiv=\"refresh\" content=\"0; URL=/webpages/index.html\" />\n </head>\n </html>",
|
|
99
|
+
"Help": "\n HTTP/0.9 400 Bad Request\n Connection: Keep-Alive\n Keep-Alive: timeout=20\n Content-Type: text/html\n <h1>Bad Request</h1>",
|
|
100
|
+
"RTSPRequest": "\n HTTP/1.0 400 Bad Request\n Connection: Keep-Alive\n Keep-Alive: timeout=20\n Content-Type: text/html\n <h1>Bad Request</h1>"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"http-title": {
|
|
104
|
+
"output": "Site doesn't have a title (text/html).",
|
|
105
|
+
"data": null
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"443": {
|
|
110
|
+
"protocol": "tcp",
|
|
111
|
+
"state": "open",
|
|
112
|
+
"reason": "syn-ack",
|
|
113
|
+
"reason_ttl": "syn-ack",
|
|
114
|
+
"service": "https",
|
|
115
|
+
"scripts": {
|
|
116
|
+
"http-title": {
|
|
117
|
+
"output": "Site doesn't have a title (text/html).",
|
|
118
|
+
"data": null
|
|
119
|
+
},
|
|
120
|
+
"ssl-cert": {
|
|
121
|
+
"output": "Subject: commonName=tplinkdeco.net/countryName=CN\nNot valid before: 2010-01-01T00:00:00\nNot valid after: 2030-12-31T00:00:00",
|
|
122
|
+
"data": {
|
|
123
|
+
"subject": {
|
|
124
|
+
"countryName": "CN",
|
|
125
|
+
"commonName": "tplinkdeco.net"
|
|
126
|
+
},
|
|
127
|
+
"issuer": {
|
|
128
|
+
"countryName": "CN",
|
|
129
|
+
"commonName": "tplinkdeco.net"
|
|
130
|
+
},
|
|
131
|
+
"pubkey": {
|
|
132
|
+
"exponent": "BIGNUM: 0x5574815bd108",
|
|
133
|
+
"bits": "2048",
|
|
134
|
+
"modulus": "BIGNUM: 0x5574815bd148",
|
|
135
|
+
"type": "rsa"
|
|
136
|
+
},
|
|
137
|
+
"extensions": [
|
|
138
|
+
{
|
|
139
|
+
"name": "X509v3 Basic Constraints",
|
|
140
|
+
"value": "CA:FALSE"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "Netscape Comment",
|
|
144
|
+
"value": "OpenSSL Generated Certificate"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "X509v3 Subject Key Identifier",
|
|
148
|
+
"value": "9D:23:AE:93:2D:A9:BB:3D:F1:4B:1E:5B:23:C5:86:30:C9:2E:B3:23"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "X509v3 Authority Key Identifier",
|
|
152
|
+
"value": "11:D9:C7:7D:04:5B:F3:B3:B7:2A:3C:02:56:88:75:63:48:A4:47:BB"
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
"validity": {
|
|
156
|
+
"notAfter": "2030-12-31T00:00:00",
|
|
157
|
+
"notBefore": "2010-01-01T00:00:00"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"ssl-date": {
|
|
162
|
+
"output": "TLS randomness does not represent time",
|
|
163
|
+
"data": null
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"1900": {
|
|
168
|
+
"protocol": "tcp",
|
|
169
|
+
"state": "open",
|
|
170
|
+
"reason": "syn-ack",
|
|
171
|
+
"reason_ttl": "syn-ack",
|
|
172
|
+
"service": "MiniUPnP 1.8",
|
|
173
|
+
"scripts": {
|
|
174
|
+
"fingerprint-strings": {
|
|
175
|
+
"output": "\n FourOhFourRequest, GetRequest: \n HTTP/1.0 404 Not Found\n Content-Type: text/html\n Connection: close\n Content-Length: 134\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY><H1>Not Found</H1>The requested URL was not found on this server.</BODY></HTML>\n GenericLines: \n 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>\n HTTPOptions: \n HTTP/1.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>\n RTSPRequest: \n RTSP/1.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>\n SIPOptions: \n SIP/2.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>",
|
|
176
|
+
"data": {
|
|
177
|
+
"FourOhFourRequest, GetRequest": "\n HTTP/1.0 404 Not Found\n Content-Type: text/html\n Connection: close\n Content-Length: 134\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY><H1>Not Found</H1>The requested URL was not found on this server.</BODY></HTML>",
|
|
178
|
+
"GenericLines": "\n 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>",
|
|
179
|
+
"HTTPOptions": "\n HTTP/1.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>",
|
|
180
|
+
"RTSPRequest": "\n RTSP/1.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>",
|
|
181
|
+
"SIPOptions": "\n SIP/2.0 501 Not Implemented\n Content-Type: text/html\n Connection: close\n Content-Length: 149\n Server: TP-LINK/TP-LINK UPnP/1.1 MiniUPnPd/1.8\n Ext:\n <HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD><BODY><H1>Not Implemented</H1>The HTTP Method is not implemented by this server.</BODY></HTML>"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
|
|
5
|
+
def response
|
|
6
|
+
if @last_response['Content-Type'].include? 'json'
|
|
7
|
+
data = JSON.load( @last_response.body )
|
|
8
|
+
else
|
|
9
|
+
data = @last_response.body
|
|
10
|
+
end
|
|
11
|
+
{
|
|
12
|
+
code: @last_response.code,
|
|
13
|
+
data: data
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def response_data
|
|
18
|
+
response[:data]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def request( method, resource = nil, parameters = nil )
|
|
22
|
+
uri = URI( "http://127.0.0.1:7331/#{resource}" )
|
|
23
|
+
|
|
24
|
+
Net::HTTP.start( uri.host, uri.port) do |http|
|
|
25
|
+
case method
|
|
26
|
+
when :get
|
|
27
|
+
uri.query = URI.encode_www_form( parameters ) if parameters
|
|
28
|
+
request = Net::HTTP::Get.new( uri )
|
|
29
|
+
|
|
30
|
+
when :post
|
|
31
|
+
request = Net::HTTP::Post.new( uri )
|
|
32
|
+
request.body = parameters.to_json
|
|
33
|
+
|
|
34
|
+
when :delete
|
|
35
|
+
request = Net::HTTP::Delete.new( uri )
|
|
36
|
+
|
|
37
|
+
when :put
|
|
38
|
+
request = Net::HTTP::Put.new( uri )
|
|
39
|
+
request.body = parameters.to_json
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@last_response = http.request( request )
|
|
43
|
+
end
|
|
44
|
+
end
|
data/examples/rest.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'peplum/nmap'
|
|
2
|
+
require 'pp'
|
|
3
|
+
require_relative 'rest/helpers'
|
|
4
|
+
|
|
5
|
+
# Boot up our REST nmap server for easy integration.
|
|
6
|
+
rest_pid = Peplum::Nmap::Application.spawn( :rest, daemonize: true )
|
|
7
|
+
at_exit { Cuboid::Processes::Manager.kill rest_pid }
|
|
8
|
+
|
|
9
|
+
# Wait for the REST server to boot up.
|
|
10
|
+
while sleep 1
|
|
11
|
+
begin
|
|
12
|
+
request :get
|
|
13
|
+
rescue Errno::ECONNREFUSED
|
|
14
|
+
next
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
break
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Assign an nmap Agent to the REST service for it to provide us with scanner Instances.
|
|
21
|
+
nmap_agent = Peplum::Nmap::Application.spawn( :agent, daemonize: true )
|
|
22
|
+
request :put, 'agent/url', nmap_agent.url
|
|
23
|
+
at_exit { nmap_agent.shutdown rescue nil }
|
|
24
|
+
|
|
25
|
+
# Create a new scanner Instance (process) and run a scan with the following options.
|
|
26
|
+
request :post, 'instances', {
|
|
27
|
+
peplum: {
|
|
28
|
+
objects: ['192.168.1.*'],
|
|
29
|
+
max_workers: 5
|
|
30
|
+
},
|
|
31
|
+
native: {
|
|
32
|
+
connect_scan: true,
|
|
33
|
+
service_scan: true,
|
|
34
|
+
default_script: true
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# The ID is used to represent that instance and allow us to manage it from here on out.
|
|
39
|
+
instance_id = response_data['id']
|
|
40
|
+
|
|
41
|
+
while sleep( 1 )
|
|
42
|
+
# Continue looping while instance status is 'busy'.
|
|
43
|
+
request :get, "instances/#{instance_id}"
|
|
44
|
+
break if !response_data['busy']
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
puts '*' * 88
|
|
48
|
+
|
|
49
|
+
# Get the scan report.
|
|
50
|
+
request :get, "instances/#{instance_id}/report.json"
|
|
51
|
+
|
|
52
|
+
# Print out the report.
|
|
53
|
+
puts JSON.pretty_generate( JSON.load( response_data['data'] ) )
|
|
54
|
+
|
|
55
|
+
# Shutdown the Instance.
|
|
56
|
+
request :delete, "instances/#{instance_id}"
|
data/examples/rpc.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'pp'
|
|
2
|
+
require 'peplum/nmap'
|
|
3
|
+
|
|
4
|
+
# Spawn an nmap Agent as a daemon.
|
|
5
|
+
nmap_agent = Peplum::Nmap::Application.spawn( :agent, daemonize: true )
|
|
6
|
+
at_exit { nmap_agent.shutdown rescue nil }
|
|
7
|
+
|
|
8
|
+
# Spawn and connect to an nmap Instance.
|
|
9
|
+
nmap = Peplum::Nmap::Application.connect( nmap_agent.spawn )
|
|
10
|
+
# Don't forget this!
|
|
11
|
+
at_exit { nmap.shutdown }
|
|
12
|
+
|
|
13
|
+
# Run a distributed scan.
|
|
14
|
+
nmap.run(
|
|
15
|
+
peplum: {
|
|
16
|
+
objects: ['192.168.1.*'],
|
|
17
|
+
max_workers: 5
|
|
18
|
+
},
|
|
19
|
+
native: {
|
|
20
|
+
connect_scan: true,
|
|
21
|
+
service_scan: true,
|
|
22
|
+
default_script: true
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Waiting to complete.
|
|
27
|
+
sleep 1 while nmap.running?
|
|
28
|
+
|
|
29
|
+
# Hooray!
|
|
30
|
+
puts JSON.pretty_generate( nmap.generate_report.data )
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'nmap/command'
|
|
2
|
+
require 'nmap/xml'
|
|
3
|
+
require 'tmpdir'
|
|
4
|
+
|
|
5
|
+
module Peplum
|
|
6
|
+
class Nmap
|
|
7
|
+
|
|
8
|
+
module Native
|
|
9
|
+
|
|
10
|
+
DEFAULT_OPTIONS = {
|
|
11
|
+
'output_normal' => '/dev/null',
|
|
12
|
+
'quiet' => true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
PING_REPORT = "#{Dir.tmpdir}/nmap-ping-#{Process.pid}.xml"
|
|
16
|
+
SCAN_REPORT = "#{Dir.tmpdir}/nmap-scan-#{Process.pid}.xml"
|
|
17
|
+
|
|
18
|
+
at_exit do
|
|
19
|
+
FileUtils.rm_f PING_REPORT
|
|
20
|
+
FileUtils.rm_f SCAN_REPORT
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run( targets, options )
|
|
24
|
+
_run options.merge( targets: targets, output_xml: SCAN_REPORT )
|
|
25
|
+
report_from_xml( SCAN_REPORT )
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def group( targets, chunks )
|
|
29
|
+
@hosts ||= self.live_hosts( targets )
|
|
30
|
+
@hosts.chunk( chunks ).reject(&:empty?)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def merge( data )
|
|
34
|
+
report = { 'hosts' => {} }
|
|
35
|
+
data.each do |d|
|
|
36
|
+
report['hosts'].merge! d['hosts']
|
|
37
|
+
end
|
|
38
|
+
report
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def live_hosts( targets )
|
|
44
|
+
_run targets: targets,
|
|
45
|
+
ping: true,
|
|
46
|
+
output_xml: PING_REPORT
|
|
47
|
+
|
|
48
|
+
hosts_from_xml( PING_REPORT )
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def set_default_options( nmap )
|
|
52
|
+
set_options( nmap, DEFAULT_OPTIONS )
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def set_options( nmap, options )
|
|
56
|
+
options.each do |k, v|
|
|
57
|
+
nmap.send "#{k}=", v
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def _run( options = {}, &block )
|
|
62
|
+
::Nmap::Command.run do |nmap|
|
|
63
|
+
set_default_options nmap
|
|
64
|
+
set_options nmap, options
|
|
65
|
+
block.call nmap if block_given?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def hosts_from_xml( xml )
|
|
70
|
+
hosts = []
|
|
71
|
+
::Nmap::XML.open( xml ) do |xml|
|
|
72
|
+
xml.each_host do |host|
|
|
73
|
+
hosts << host.ip
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
hosts
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def report_from_xml( xml )
|
|
80
|
+
report_data = {}
|
|
81
|
+
::Nmap::XML.open( xml ) do |xml|
|
|
82
|
+
xml.each_host do |host|
|
|
83
|
+
report_data['hosts'] ||= {}
|
|
84
|
+
report_data['hosts'][host.ip] = host_to_hash( host )
|
|
85
|
+
|
|
86
|
+
report_data['hosts'][host.ip]['ports'] = {}
|
|
87
|
+
host.each_port do |port|
|
|
88
|
+
report_data['hosts'][host.ip]['ports'][port.number] = port_to_hash( port )
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
report_data
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def host_to_hash( host )
|
|
96
|
+
h = {}
|
|
97
|
+
%w(start_time end_time status addresses mac vendor ipv4 ipv6 hostname hostnames os uptime).each do |k|
|
|
98
|
+
v = host.send( k )
|
|
99
|
+
next if !v
|
|
100
|
+
|
|
101
|
+
if v.is_a? Array
|
|
102
|
+
h[k] = v.map(&:to_s)
|
|
103
|
+
else
|
|
104
|
+
h[k] = v.to_s
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if host.host_script
|
|
109
|
+
h['scripts'] = {}
|
|
110
|
+
host.host_script.scripts.each do |name, script|
|
|
111
|
+
h['scripts'][name] = {
|
|
112
|
+
output: script.output,
|
|
113
|
+
data: script.data
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
h
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def port_to_hash( port )
|
|
122
|
+
h = {}
|
|
123
|
+
|
|
124
|
+
%w(protocol state reason reason_ttl).each do |k|
|
|
125
|
+
h[k] = port.send( k )
|
|
126
|
+
end
|
|
127
|
+
h['service'] = port.service.to_s
|
|
128
|
+
|
|
129
|
+
h['scripts'] ||= {}
|
|
130
|
+
port.scripts.each do |name, script|
|
|
131
|
+
h['scripts'][name] = {
|
|
132
|
+
output: script.output,
|
|
133
|
+
data: script.data
|
|
134
|
+
}
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
h
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
extend self
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
end
|
data/lib/peplum/nmap.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'peplum'
|
|
4
|
+
|
|
5
|
+
module Peplum
|
|
6
|
+
class Nmap
|
|
7
|
+
|
|
8
|
+
require_relative "nmap/version"
|
|
9
|
+
require_relative "nmap/native"
|
|
10
|
+
|
|
11
|
+
class Error < Peplum::Error; end
|
|
12
|
+
|
|
13
|
+
class Application < Peplum::Application
|
|
14
|
+
def native_app
|
|
15
|
+
Native
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
data/peplum-nmap.gemspec
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/peplum/nmap/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "peplum-nmap"
|
|
7
|
+
spec.version = Peplum::Nmap::VERSION
|
|
8
|
+
spec.authors = ["Tasos Laskos"]
|
|
9
|
+
spec.email = ["tasos.laskos@ecsypno.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Distributed NMap."
|
|
12
|
+
spec.description = "Distributed NMap backed by Peplum."
|
|
13
|
+
spec.homepage = "http://ecsypno.com/"
|
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
|
15
|
+
|
|
16
|
+
spec.files = Dir.glob( 'bin/*')
|
|
17
|
+
spec.files += Dir.glob( 'lib/**/*')
|
|
18
|
+
spec.files += Dir.glob( 'examples/**/*')
|
|
19
|
+
spec.files += %w(peplum-nmap.gemspec)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
spec.add_dependency "peplum"
|
|
23
|
+
spec.add_dependency 'ruby-nmap'
|
|
24
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: peplum-nmap
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tasos Laskos
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-05-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: peplum
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: ruby-nmap
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: Distributed NMap backed by Peplum.
|
|
42
|
+
email:
|
|
43
|
+
- tasos.laskos@ecsypno.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- bin/console
|
|
49
|
+
- bin/setup
|
|
50
|
+
- examples/output.json
|
|
51
|
+
- examples/rest.rb
|
|
52
|
+
- examples/rest/helpers.rb
|
|
53
|
+
- examples/rpc.rb
|
|
54
|
+
- lib/peplum/nmap.rb
|
|
55
|
+
- lib/peplum/nmap/native.rb
|
|
56
|
+
- lib/peplum/nmap/version.rb
|
|
57
|
+
- peplum-nmap.gemspec
|
|
58
|
+
homepage: http://ecsypno.com/
|
|
59
|
+
licenses: []
|
|
60
|
+
metadata: {}
|
|
61
|
+
post_install_message:
|
|
62
|
+
rdoc_options: []
|
|
63
|
+
require_paths:
|
|
64
|
+
- lib
|
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 2.6.0
|
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
requirements: []
|
|
76
|
+
rubygems_version: 3.4.13
|
|
77
|
+
signing_key:
|
|
78
|
+
specification_version: 4
|
|
79
|
+
summary: Distributed NMap.
|
|
80
|
+
test_files: []
|