Skip to content

Commit 99c9e76

Browse files
Merge branch 'master' into master
2 parents e70804e + ef21a75 commit 99c9e76

File tree

9 files changed

+275
-2
lines changed

9 files changed

+275
-2
lines changed

integration_tests/pptp/chap-secrets

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Secrets for authentication using PAP
2+
# client server secret acceptable local IP addresses
3+
username * password *

integration_tests/pptp/cleanup.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env bash
2+
3+
set +e
4+
5+
echo "pptp/cleanup: Tests cleanup for pptp"
6+
7+
CONTAINER_NAME=zgrab_pptp
8+
9+
docker stop $CONTAINER_NAME

integration_tests/pptp/setup.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bash
2+
3+
echo "pptp/setup: Tests setup for pptp"
4+
5+
CONTAINER_TAG="mobtitude/vpn-pptp"
6+
CONTAINER_NAME="zgrab_pptp"
7+
8+
# If the container is already running, use it.
9+
if docker ps --filter "name=$CONTAINER_NAME" | grep -q $CONTAINER_NAME; then
10+
echo "pptp/setup: Container $CONTAINER_NAME already running -- nothing to setup"
11+
exit 0
12+
fi
13+
14+
DOCKER_RUN_FLAGS="--rm --privileged --name $CONTAINER_NAME -td -v ./chap-secrets:/etc/ppp/chap-secrets"
15+
16+
# If it is not running, try launching it -- on success, use that.
17+
echo "pptp/setup: Trying to launch $CONTAINER_NAME..."
18+
if ! docker run $DOCKER_RUN_FLAGS $CONTAINER_TAG; then
19+
echo "failed"
20+
# echo "pptp/setup: Building docker image $CONTAINER_TAG..."
21+
# # If it fails, build it from ./container/Dockerfile
22+
# docker build -t $CONTAINER_TAG ./container
23+
# # Try again
24+
# echo "pptp/setup: Launching $CONTAINER_NAME..."
25+
# docker run $DOCKER_RUN_FLAGS $CONTAINER_TAG
26+
fi

integration_tests/pptp/test.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
MODULE_DIR=$(dirname $0)
5+
ZGRAB_ROOT=$(git rev-parse --show-toplevel)
6+
ZGRAB_OUTPUT=$ZGRAB_ROOT/zgrab-output
7+
8+
mkdir -p $ZGRAB_OUTPUT/pptp
9+
10+
CONTAINER_NAME=zgrab_pptp
11+
12+
OUTPUT_FILE=$ZGRAB_OUTPUT/pptp/pptp.json
13+
14+
echo "pptp/test: Tests runner for pptp"
15+
# TODO FIXME: Add any necessary flags or additional tests
16+
CONTAINER_NAME=$CONTAINER_NAME $ZGRAB_ROOT/docker-runner/docker-run.sh pptp > $OUTPUT_FILE
17+
18+
# Dump the docker logs
19+
echo "pptp/test: BEGIN docker logs from $CONTAINER_NAME [{("
20+
docker logs --tail all $CONTAINER_NAME
21+
echo ")}] END docker logs from $CONTAINER_NAME"
22+
23+
# TODO: If there are any other relevant log files, dump those to stdout here.

modules/http/scanner.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,15 @@ func (scan *scan) Grab() *zgrab2.ScanError {
570570
}
571571

572572
// Application-specific logic for retrying HTTP as HTTPS; if condition matches, return protocol error
573-
if scan.scanner.config.FailHTTPToHTTPS && scan.results.Response.StatusCode == 400 && readLen < 1024 && readLen > 24 {
573+
bodyTextLen := int64(len(bodyText))
574+
if scan.scanner.config.FailHTTPToHTTPS && scan.results.Response.StatusCode == 400 && bodyTextLen < 1024 && bodyTextLen > 24 {
574575
// Apache: "You're speaking plain HTTP to an SSL-enabled server port"
575576
// NGINX: "The plain HTTP request was sent to HTTPS port"
576577
var sliceLen int64 = 128
577578
if readLen < sliceLen {
578579
sliceLen = readLen
579580
}
580581

581-
bodyTextLen := int64(len(bodyText))
582582
if bodyTextLen < sliceLen {
583583
sliceLen = bodyTextLen
584584
}

modules/pptp.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package modules
2+
3+
import "github.com/zmap/zgrab2/modules/pptp"
4+
5+
func init() {
6+
pptp.RegisterModule()
7+
}

modules/pptp/scanner.go

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Package pptp contains the zgrab2 Module implementation for PPTP.
2+
package pptp
3+
4+
import (
5+
"encoding/binary"
6+
"fmt"
7+
"net"
8+
"time"
9+
10+
log "github.com/sirupsen/logrus"
11+
"github.com/zmap/zgrab2"
12+
)
13+
14+
// ScanResults is the output of the scan.
15+
type ScanResults struct {
16+
// Banner is the initial data banner sent by the server.
17+
Banner string `json:"banner,omitempty"`
18+
19+
// ControlMessage is the received PPTP control message.
20+
ControlMessage string `json:"control_message,omitempty"`
21+
}
22+
23+
// Flags are the PPTP-specific command-line flags.
24+
type Flags struct {
25+
zgrab2.BaseFlags
26+
Verbose bool `long:"verbose" description:"More verbose logging, include debug fields in the scan results"`
27+
}
28+
29+
// Module implements the zgrab2.Module interface.
30+
type Module struct {
31+
}
32+
33+
// Scanner implements the zgrab2.Scanner interface, and holds the state
34+
// for a single scan.
35+
type Scanner struct {
36+
config *Flags
37+
}
38+
39+
// RegisterModule registers the pptp zgrab2 module.
40+
func RegisterModule() {
41+
var module Module
42+
_, err := zgrab2.AddCommand("pptp", "PPTP", module.Description(), 1723, &module)
43+
if err != nil {
44+
log.Fatal(err)
45+
}
46+
}
47+
48+
// NewFlags returns the default flags object to be filled in with the
49+
// command-line arguments.
50+
func (m *Module) NewFlags() interface{} {
51+
return new(Flags)
52+
}
53+
54+
// NewScanner returns a new Scanner instance.
55+
func (m *Module) NewScanner() zgrab2.Scanner {
56+
return new(Scanner)
57+
}
58+
59+
// Description returns an overview of this module.
60+
func (m *Module) Description() string {
61+
return "Scan for PPTP"
62+
}
63+
64+
// Validate flags
65+
func (f *Flags) Validate(args []string) (err error) {
66+
return
67+
}
68+
69+
// Help returns this module's help string.
70+
func (f *Flags) Help() string {
71+
return ""
72+
}
73+
74+
// Protocol returns the protocol identifier for the scanner.
75+
func (s *Scanner) Protocol() string {
76+
return "pptp"
77+
}
78+
79+
// Init initializes the Scanner instance with the flags from the command line.
80+
func (s *Scanner) Init(flags zgrab2.ScanFlags) error {
81+
f, _ := flags.(*Flags)
82+
s.config = f
83+
return nil
84+
}
85+
86+
// InitPerSender does nothing in this module.
87+
func (s *Scanner) InitPerSender(senderID int) error {
88+
return nil
89+
}
90+
91+
// GetName returns the configured name for the Scanner.
92+
func (s *Scanner) GetName() string {
93+
return s.config.Name
94+
}
95+
96+
// GetTrigger returns the Trigger defined in the Flags.
97+
func (scanner *Scanner) GetTrigger() string {
98+
return scanner.config.Trigger
99+
}
100+
101+
// PPTP Start-Control-Connection-Request message constants
102+
const (
103+
PPTP_MAGIC_COOKIE = 0x1A2B3C4D
104+
PPTP_CONTROL_MESSAGE = 1
105+
PPTP_START_CONN_REQUEST = 1
106+
PPTP_PROTOCOL_VERSION = 0x0100 // Split into two 16-bit values for binary.BigEndian.PutUint16
107+
)
108+
109+
// Connection holds the state for a single connection to the PPTP server.
110+
type Connection struct {
111+
config *Flags
112+
results ScanResults
113+
conn net.Conn
114+
}
115+
116+
// Create the Start-Control-Connection-Request message
117+
func createSCCRMessage() []byte {
118+
message := make([]byte, 156)
119+
binary.BigEndian.PutUint16(message[0:2], 156) // Length
120+
binary.BigEndian.PutUint16(message[2:4], PPTP_CONTROL_MESSAGE) // PPTP Message Type
121+
binary.BigEndian.PutUint32(message[4:8], PPTP_MAGIC_COOKIE) // Magic Cookie
122+
binary.BigEndian.PutUint16(message[8:10], PPTP_START_CONN_REQUEST) // Control Message Type
123+
binary.BigEndian.PutUint16(message[10:12], uint16(PPTP_PROTOCOL_VERSION>>16)) // Protocol Version (high 16 bits)
124+
binary.BigEndian.PutUint16(message[12:14], uint16(PPTP_PROTOCOL_VERSION&0xFFFF)) // Protocol Version (low 16 bits)
125+
binary.BigEndian.PutUint32(message[14:18], 0) // Framing Capabilities
126+
binary.BigEndian.PutUint32(message[18:22], 0) // Bearer Capabilities
127+
binary.BigEndian.PutUint16(message[22:24], 0) // Maximum Channels
128+
binary.BigEndian.PutUint16(message[24:26], 0) // Firmware Revision
129+
copy(message[26:90], "ZGRAB2-SCANNER") // Host Name
130+
copy(message[90:], "ZGRAB2") // Vendor Name
131+
return message
132+
}
133+
134+
// Read response from the PPTP server
135+
func (pptp *Connection) readResponse() (string, error) {
136+
buffer := make([]byte, 1024)
137+
pptp.conn.SetReadDeadline(time.Now().Add(5 * time.Second))
138+
n, err := pptp.conn.Read(buffer)
139+
if err != nil {
140+
return "", err
141+
}
142+
return string(buffer[:n]), nil
143+
}
144+
145+
// Scan performs the configured scan on the PPTP server
146+
func (s *Scanner) Scan(t zgrab2.ScanTarget) (status zgrab2.ScanStatus, result interface{}, thrown error) {
147+
var err error
148+
conn, err := t.Open(&s.config.BaseFlags)
149+
if err != nil {
150+
return zgrab2.TryGetScanStatus(err), nil, fmt.Errorf("error opening connection: %w", err)
151+
}
152+
cn := conn
153+
defer func() {
154+
cn.Close()
155+
}()
156+
157+
results := ScanResults{}
158+
159+
pptp := Connection{conn: cn, config: s.config, results: results}
160+
161+
// Send Start-Control-Connection-Request message
162+
request := createSCCRMessage()
163+
_, err = pptp.conn.Write(request)
164+
if err != nil {
165+
return zgrab2.TryGetScanStatus(err), &pptp.results, fmt.Errorf("error sending PPTP SCCR message: %w", err)
166+
}
167+
168+
// Read the response
169+
response, err := pptp.readResponse()
170+
if err != nil {
171+
return zgrab2.TryGetScanStatus(err), &pptp.results, fmt.Errorf("error reading PPTP response: %w", err)
172+
}
173+
174+
// Store the banner and control message
175+
pptp.results.Banner = string(request)
176+
pptp.results.ControlMessage = response
177+
178+
return zgrab2.SCAN_SUCCESS, &pptp.results, nil
179+
}

zgrab2_schemas/zgrab2/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
from . import banner
2424
from . import amqp091
2525
from . import mqtt
26+
from . import pptp

zgrab2_schemas/zgrab2/pptp.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# zschema sub-schema for zgrab2's PPTP module
2+
# Registers zgrab2-pptp globally, and pptp with the main zgrab2 schema.
3+
from zschema.leaves import *
4+
from zschema.compounds import *
5+
import zschema.registry
6+
7+
from . import zgrab2
8+
9+
# Schema for ScanResults struct
10+
pptp_scan_response = SubRecord(
11+
{
12+
"banner": String(),
13+
"control_message": String(),
14+
}
15+
)
16+
17+
pptp_scan = SubRecord(
18+
{
19+
"result": pptp_scan_response,
20+
},
21+
extends=zgrab2.base_scan_response,
22+
)
23+
24+
zschema.registry.register_schema("zgrab2-pptp", pptp_scan)
25+
zgrab2.register_scan_response_type("pptp", pptp_scan)

0 commit comments

Comments
 (0)