-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from stevenaldinger/feature/nmap-protocol-scan
add nmap protocol detection
- Loading branch information
Showing
6 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// environment variable config | ||
variable "target_host" { | ||
type = "string" | ||
} | ||
|
||
resource "nmap_protocol_detection" "nmap" { | ||
host = "${var.target_host}" | ||
type = "protocol_detection" | ||
} | ||
|
||
resource "metasploit" "metasploit" { | ||
for_each = "${nmap.ssh}" | ||
exploit = "auxiliary/scanner/ssh/ssh_login" | ||
options = { | ||
RHOSTS = "${var.target_host}" | ||
RPORT = "${each.key}" | ||
USERPASS_FILE = "/usr/share/metasploit-framework/data/wordlists/root_userpass.txt" | ||
} | ||
} | ||
|
||
resource "sslscan" "sslscan" { | ||
for_each = "${nmap.https}" | ||
host = "${var.target_host}" | ||
} |
3 changes: 3 additions & 0 deletions
3
internal/app/decker/plugins/nmap_protocol_detection/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# nmap decker plugin | ||
|
||
[network mapper](https://nmap.org/) |
176 changes: 176 additions & 0 deletions
176
internal/app/decker/plugins/nmap_protocol_detection/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"github.com/stevenaldinger/decker/pkg/gocty" | ||
"github.com/zclconf/go-cty/cty" | ||
"os" | ||
"os/exec" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
func stringToLines(s string) (lines []string, err error) { | ||
scanner := bufio.NewScanner(strings.NewReader(s)) | ||
for scanner.Scan() { | ||
lines = append(lines, scanner.Text()) | ||
} | ||
err = scanner.Err() | ||
return lines, err | ||
} | ||
|
||
// https://www.dotnetperls.com/duplicates-go | ||
func removeDuplicates(elements []string) []string { | ||
encountered := map[string]bool{} | ||
|
||
// Create a map of all unique elements. | ||
for v:= range elements { | ||
encountered[elements[v]] = true | ||
} | ||
|
||
// Place all keys from the map into a slice. | ||
result := []string{} | ||
for key, _ := range encountered { | ||
result = append(result, key) | ||
} | ||
return result | ||
} | ||
|
||
type plugin string | ||
|
||
// --- wants input: --- | ||
// inputsMap{ | ||
// "host": "example.com", | ||
// } | ||
// | ||
// --- gives output: --- | ||
// resultsMap{ | ||
// "raw_output": "...", | ||
// } | ||
func (p plugin) Run(inputsMap, resultsMap *map[string]cty.Value) { | ||
var ( | ||
cmdOut []byte | ||
err error | ||
cmdArgs []string | ||
outputByLine []string | ||
services []string | ||
servicesMap map[string] []string | ||
) | ||
|
||
decoder := gocty.Decoder{} | ||
encoder := gocty.Encoder{} | ||
servicesMap = map[string][]string{} | ||
|
||
targetHost := decoder.GetString((*inputsMap)["host"]) | ||
scanType := decoder.GetString((*inputsMap)["type"]) | ||
|
||
cmdName := "nmap" | ||
if scanType == "protocol_detection" { | ||
cmdArgs = []string{"-O", "-oG", "-", targetHost} | ||
} else { | ||
cmdArgs = []string{targetHost} | ||
} | ||
|
||
if cmdOut, err = exec.Command(cmdName, cmdArgs...).Output(); err != nil { | ||
fmt.Fprintln(os.Stderr, "There was an error running nmap command: ", err) | ||
return | ||
} | ||
|
||
output := string(cmdOut) | ||
|
||
if scanType == "protocol_detection" { | ||
// Host: 93.184.216.34 () Status: Up | ||
// Host: 93.184.216.34 () Ports: 80/open/tcp//http///, 443/open/tcp//https///, 1935/closed/tcp//rtmp/// Ignored State: filtered (997) Seq Index: 252 IP ID Seq: Randomized | ||
// # Nmap done at Mon Mar 11 19:02:34 2019 -- 1 IP address (1 host up) scanned in 8.76 seconds | ||
|
||
// fmt.Println("Output:", output) | ||
|
||
if outputByLine, err = stringToLines(output); err != nil { | ||
fmt.Fprintln(os.Stderr, "Error occured while converting nmap protocol to array of strings: ", err) | ||
return | ||
} | ||
|
||
splitOutput := strings.Split(outputByLine[2], "Ports: ") | ||
portsOpen := splitOutput[1] | ||
portsOpenArray := strings.Split(portsOpen, ",") | ||
|
||
for _, portInfo := range portsOpenArray { | ||
// fmt.Println("Port:", portInfo) | ||
|
||
portInfoSplit := strings.Split(portInfo, "/") | ||
// fmt.Println("Len(portInfoSplit):", len(portInfoSplit)) | ||
parsedPort := portInfoSplit[0] | ||
parsedState := portInfoSplit[1] | ||
parsedTransportProtocol := portInfoSplit[2] | ||
parsedServiceProtocol := portInfoSplit[4] | ||
// fmt.Println("Port:", parsedPort) | ||
// fmt.Println("State:", parsedState) | ||
// fmt.Println("Transport:", parsedTransportProtocol) | ||
// fmt.Println("Service:", parsedServiceProtocol) | ||
portInfoMap := map[string]cty.Value{ | ||
"port": encoder.StringVal(parsedPort), | ||
"state": encoder.StringVal(parsedState), | ||
"transport": encoder.StringVal(parsedTransportProtocol), | ||
"service": encoder.StringVal(parsedServiceProtocol), | ||
} | ||
|
||
(*resultsMap)[parsedPort] = encoder.MapVal(portInfoMap) | ||
// (*resultsMap)[parsedPort] = encoder.StringVal(parsedServiceProtocol) | ||
|
||
if _, ok := servicesMap[parsedServiceProtocol]; !ok { | ||
servicesMap[parsedServiceProtocol] = []string{} | ||
} | ||
servicesMap[parsedServiceProtocol] = removeDuplicates(append(servicesMap[parsedServiceProtocol], parsedPort)) | ||
services = append(services, parsedServiceProtocol) | ||
} | ||
|
||
services = removeDuplicates(services) | ||
|
||
// set everything that's not open to false so value is defined in HCL configs | ||
for i := 1; i <= 30000; i++ { | ||
if _, ok := (*resultsMap)[strconv.Itoa(i)]; !ok { | ||
portInfoMap := map[string]cty.Value{ | ||
"port": encoder.StringVal(strconv.Itoa(i)), | ||
"state": encoder.StringVal("closed"), | ||
"transport": encoder.StringVal(""), | ||
"service": encoder.StringVal(""), | ||
} | ||
|
||
(*resultsMap)[strconv.Itoa(i)] = encoder.MapVal(portInfoMap) | ||
// (*resultsMap)[strconv.Itoa(i)] = encoder.StringVal("") | ||
} | ||
} | ||
|
||
var servicesCty = []cty.Value{} | ||
for _, service := range services { | ||
servicesCty = append(servicesCty, encoder.StringVal(service)) | ||
|
||
var portsWithServiceCty = []cty.Value{} | ||
for _, port := range servicesMap[service] { | ||
portsWithServiceCty = append(portsWithServiceCty, encoder.StringVal(port)) | ||
} | ||
(*resultsMap)[service] = encoder.ListVal(portsWithServiceCty) | ||
} | ||
|
||
(*resultsMap)["services"] = encoder.ListVal(servicesCty) | ||
} | ||
// } else { | ||
// portInfoMap := map[string]cty.Value{ | ||
// "port": encoder.StringVal(strconv.Itoa(i)), | ||
// "state": encoder.StringVal("closed"), | ||
// "transport": encoder.StringVal(""), | ||
// "service": encoder.StringVal(""), | ||
// } | ||
// (*resultsMap)[strconv.Itoa(i)] = encoder.MapVal(portInfoMap) | ||
// (*resultsMap)["protocol"] = encoder.StringVal("") | ||
// } | ||
|
||
(*resultsMap)["raw_output"] = encoder.StringVal(output) | ||
} | ||
|
||
// Plugin is an implementation of github.com/stevenaldinger/decker/pkg/plugins.Plugin | ||
// All this includes is a single function, "Run(*map[string]string, *map[string]string)" | ||
// which takes a map of inputs and an empty map of outputs that the Plugin | ||
// is expected to populate | ||
var Plugin plugin |
25 changes: 25 additions & 0 deletions
25
internal/app/decker/plugins/nmap_protocol_detection/nmap_protocol_detection.hcl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// inputs must be given in the main config spec | ||
// if no default is given, considered to be required | ||
// input "arguments" { | ||
// type = "list" | ||
// default = [] | ||
// } | ||
input "type" { | ||
type = "string" | ||
default = "port_scan" | ||
} | ||
|
||
input "host" { | ||
type = "string" | ||
default = "example.com" | ||
} | ||
|
||
input "plugin_enabled" { | ||
type = "string" | ||
default = "true" | ||
} | ||
|
||
// outputs the plugin will return | ||
output "raw_output" { | ||
type = "string" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters