Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/docker/docker-runner/ubuntu-24.04
Browse files Browse the repository at this point in the history
  • Loading branch information
phillip-stephens authored Jan 27, 2025
2 parents c3374cb + ef21a75 commit 5780e09
Show file tree
Hide file tree
Showing 15 changed files with 291 additions and 19 deletions.
17 changes: 8 additions & 9 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
integration-test:
name: Integration Test
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Check out source
uses: actions/checkout@v4
Expand All @@ -58,17 +58,16 @@ jobs:
- name: Install dependencies
run: |
set -e
sudo wget https://github.com/jmespath/jp/releases/download/0.2.1/jp-linux-amd64 -O /usr/local/bin/jp
sudo chmod +x /usr/local/bin/jp
# Install Python 2.7
sudo apt update
sudo apt install -y python2
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
sudo python2 get-pip.py
# Install latest Python
sudo apt install -y python3 jp python3-pip
python3 -m venv venv
source venv/bin/activate
# Install Python dependencies
pip2 install --user zschema
pip2 install --user -r requirements.txt
pip install zschema
pip install -r requirements.txt
- name: Run tests
run: |
source venv/bin/activate
make integration-test
2 changes: 1 addition & 1 deletion integration_tests/mssql/cleanup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set +e

CONTAINER_NAME="zgrab_mssql-2017-linux"
CONTAINER_NAME="zgrab_mssql-2022-linux"

echo "mssql/cleanup: Tests cleanup for mssql"

Expand Down
6 changes: 3 additions & 3 deletions integration_tests/mssql/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
echo "mssql/setup: Tests setup for mssql"

CONTAINER_IMAGE="mcr.microsoft.com/mssql/server"
CONTAINER_VERSION="2017-latest"
CONTAINER_NAME="zgrab_mssql-2017-linux"
CONTAINER_VERSION="2022-latest"
CONTAINER_NAME="zgrab_mssql-2022-linux"

# Supported MSSQL_PRODUCT_ID values are Developer, Express, Standard, Enterprise, EnterpriseCore
MSSQL_PRODUCT_ID="Enterprise"
Expand All @@ -14,7 +14,7 @@ if docker ps --filter "name=$CONTAINER_NAME" | grep $CONTAINER_NAME; then
exit 0
fi

docker run -td --rm -e "MSSQL_PID=$MSSQL_PRODUCT_ID" -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=$(openssl rand -base64 12)" --name $CONTAINER_NAME $CONTAINER_IMAGE:$CONTAINER_VERSION
docker run -td --rm -e "MSSQL_PID=$MSSQL_PRODUCT_ID" -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=$(openssl rand -base64 12)" --platform "linux/amd64" --name $CONTAINER_NAME $CONTAINER_IMAGE:$CONTAINER_VERSION

echo -n "mssql/setup: Waiting on $CONTAINER_NAME..."

Expand Down
4 changes: 2 additions & 2 deletions integration_tests/mssql/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ TEST_ROOT=$MODULE_DIR/..
ZGRAB_ROOT=$(git rev-parse --show-toplevel)
ZGRAB_OUTPUT=$ZGRAB_ROOT/zgrab-output

CONTAINER_NAME="zgrab_mssql-2017-linux"
CONTAINER_NAME="zgrab_mssql-2022-linux"

mkdir -p $ZGRAB_OUTPUT/mssql

OUTPUT_FILE="$ZGRAB_OUTPUT/mssql/2017-linux.json"
OUTPUT_FILE="$ZGRAB_OUTPUT/mssql/2022-linux.json"

echo "mssql/test: Tests runner for mssql"
CONTAINER_NAME=$CONTAINER_NAME $ZGRAB_ROOT/docker-runner/docker-run.sh mssql > $OUTPUT_FILE
Expand Down
3 changes: 3 additions & 0 deletions integration_tests/pptp/chap-secrets
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Secrets for authentication using PAP
# client server secret acceptable local IP addresses
username * password *
9 changes: 9 additions & 0 deletions integration_tests/pptp/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set +e

echo "pptp/cleanup: Tests cleanup for pptp"

CONTAINER_NAME=zgrab_pptp

docker stop $CONTAINER_NAME
26 changes: 26 additions & 0 deletions integration_tests/pptp/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash

echo "pptp/setup: Tests setup for pptp"

CONTAINER_TAG="mobtitude/vpn-pptp"
CONTAINER_NAME="zgrab_pptp"

# If the container is already running, use it.
if docker ps --filter "name=$CONTAINER_NAME" | grep -q $CONTAINER_NAME; then
echo "pptp/setup: Container $CONTAINER_NAME already running -- nothing to setup"
exit 0
fi

DOCKER_RUN_FLAGS="--rm --privileged --name $CONTAINER_NAME -td -v ./chap-secrets:/etc/ppp/chap-secrets"

# If it is not running, try launching it -- on success, use that.
echo "pptp/setup: Trying to launch $CONTAINER_NAME..."
if ! docker run $DOCKER_RUN_FLAGS $CONTAINER_TAG; then
echo "failed"
# echo "pptp/setup: Building docker image $CONTAINER_TAG..."
# # If it fails, build it from ./container/Dockerfile
# docker build -t $CONTAINER_TAG ./container
# # Try again
# echo "pptp/setup: Launching $CONTAINER_NAME..."
# docker run $DOCKER_RUN_FLAGS $CONTAINER_TAG
fi
23 changes: 23 additions & 0 deletions integration_tests/pptp/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash

set -e
MODULE_DIR=$(dirname $0)
ZGRAB_ROOT=$(git rev-parse --show-toplevel)
ZGRAB_OUTPUT=$ZGRAB_ROOT/zgrab-output

mkdir -p $ZGRAB_OUTPUT/pptp

CONTAINER_NAME=zgrab_pptp

OUTPUT_FILE=$ZGRAB_OUTPUT/pptp/pptp.json

echo "pptp/test: Tests runner for pptp"
# TODO FIXME: Add any necessary flags or additional tests
CONTAINER_NAME=$CONTAINER_NAME $ZGRAB_ROOT/docker-runner/docker-run.sh pptp > $OUTPUT_FILE

# Dump the docker logs
echo "pptp/test: BEGIN docker logs from $CONTAINER_NAME [{("
docker logs --tail all $CONTAINER_NAME
echo ")}] END docker logs from $CONTAINER_NAME"

# TODO: If there are any other relevant log files, dump those to stdout here.
2 changes: 1 addition & 1 deletion integration_tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ for protocol in $(ls $ZGRAB_OUTPUT); do
echo "Validating $target [{("
cat $target
echo ")}]:"
if ! python2 -m zschema validate zgrab2 $target --path . --module zgrab2_schemas.zgrab2 ; then
if ! python3 -m zschema validate zgrab2 $target --path . --module zgrab2_schemas.zgrab2 ; then
echo "Schema validation failed for $protocol/$outfile"
err="schema failure@$protocol/$outfile"
if [[ $status -eq 0 ]]; then
Expand Down
4 changes: 2 additions & 2 deletions modules/http/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,15 +570,15 @@ func (scan *scan) Grab() *zgrab2.ScanError {
}

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

bodyTextLen := int64(len(bodyText))
if bodyTextLen < sliceLen {
sliceLen = bodyTextLen
}
Expand Down
7 changes: 7 additions & 0 deletions modules/pptp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package modules

import "github.com/zmap/zgrab2/modules/pptp"

func init() {
pptp.RegisterModule()
}
179 changes: 179 additions & 0 deletions modules/pptp/scanner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Package pptp contains the zgrab2 Module implementation for PPTP.
package pptp

import (
"encoding/binary"
"fmt"
"net"
"time"

log "github.com/sirupsen/logrus"
"github.com/zmap/zgrab2"
)

// ScanResults is the output of the scan.
type ScanResults struct {
// Banner is the initial data banner sent by the server.
Banner string `json:"banner,omitempty"`

// ControlMessage is the received PPTP control message.
ControlMessage string `json:"control_message,omitempty"`
}

// Flags are the PPTP-specific command-line flags.
type Flags struct {
zgrab2.BaseFlags
Verbose bool `long:"verbose" description:"More verbose logging, include debug fields in the scan results"`
}

// Module implements the zgrab2.Module interface.
type Module struct {
}

// Scanner implements the zgrab2.Scanner interface, and holds the state
// for a single scan.
type Scanner struct {
config *Flags
}

// RegisterModule registers the pptp zgrab2 module.
func RegisterModule() {
var module Module
_, err := zgrab2.AddCommand("pptp", "PPTP", module.Description(), 1723, &module)
if err != nil {
log.Fatal(err)
}
}

// NewFlags returns the default flags object to be filled in with the
// command-line arguments.
func (m *Module) NewFlags() interface{} {
return new(Flags)
}

// NewScanner returns a new Scanner instance.
func (m *Module) NewScanner() zgrab2.Scanner {
return new(Scanner)
}

// Description returns an overview of this module.
func (m *Module) Description() string {
return "Scan for PPTP"
}

// Validate flags
func (f *Flags) Validate(args []string) (err error) {
return
}

// Help returns this module's help string.
func (f *Flags) Help() string {
return ""
}

// Protocol returns the protocol identifier for the scanner.
func (s *Scanner) Protocol() string {
return "pptp"
}

// Init initializes the Scanner instance with the flags from the command line.
func (s *Scanner) Init(flags zgrab2.ScanFlags) error {
f, _ := flags.(*Flags)
s.config = f
return nil
}

// InitPerSender does nothing in this module.
func (s *Scanner) InitPerSender(senderID int) error {
return nil
}

// GetName returns the configured name for the Scanner.
func (s *Scanner) GetName() string {
return s.config.Name
}

// GetTrigger returns the Trigger defined in the Flags.
func (scanner *Scanner) GetTrigger() string {
return scanner.config.Trigger
}

// PPTP Start-Control-Connection-Request message constants
const (
PPTP_MAGIC_COOKIE = 0x1A2B3C4D
PPTP_CONTROL_MESSAGE = 1
PPTP_START_CONN_REQUEST = 1
PPTP_PROTOCOL_VERSION = 0x0100 // Split into two 16-bit values for binary.BigEndian.PutUint16
)

// Connection holds the state for a single connection to the PPTP server.
type Connection struct {
config *Flags
results ScanResults
conn net.Conn
}

// Create the Start-Control-Connection-Request message
func createSCCRMessage() []byte {
message := make([]byte, 156)
binary.BigEndian.PutUint16(message[0:2], 156) // Length
binary.BigEndian.PutUint16(message[2:4], PPTP_CONTROL_MESSAGE) // PPTP Message Type
binary.BigEndian.PutUint32(message[4:8], PPTP_MAGIC_COOKIE) // Magic Cookie
binary.BigEndian.PutUint16(message[8:10], PPTP_START_CONN_REQUEST) // Control Message Type
binary.BigEndian.PutUint16(message[10:12], uint16(PPTP_PROTOCOL_VERSION>>16)) // Protocol Version (high 16 bits)
binary.BigEndian.PutUint16(message[12:14], uint16(PPTP_PROTOCOL_VERSION&0xFFFF)) // Protocol Version (low 16 bits)
binary.BigEndian.PutUint32(message[14:18], 0) // Framing Capabilities
binary.BigEndian.PutUint32(message[18:22], 0) // Bearer Capabilities
binary.BigEndian.PutUint16(message[22:24], 0) // Maximum Channels
binary.BigEndian.PutUint16(message[24:26], 0) // Firmware Revision
copy(message[26:90], "ZGRAB2-SCANNER") // Host Name
copy(message[90:], "ZGRAB2") // Vendor Name
return message
}

// Read response from the PPTP server
func (pptp *Connection) readResponse() (string, error) {
buffer := make([]byte, 1024)
pptp.conn.SetReadDeadline(time.Now().Add(5 * time.Second))
n, err := pptp.conn.Read(buffer)
if err != nil {
return "", err
}
return string(buffer[:n]), nil
}

// Scan performs the configured scan on the PPTP server
func (s *Scanner) Scan(t zgrab2.ScanTarget) (status zgrab2.ScanStatus, result interface{}, thrown error) {
var err error
conn, err := t.Open(&s.config.BaseFlags)
if err != nil {
return zgrab2.TryGetScanStatus(err), nil, fmt.Errorf("error opening connection: %w", err)
}
cn := conn
defer func() {
cn.Close()
}()

results := ScanResults{}

pptp := Connection{conn: cn, config: s.config, results: results}

// Send Start-Control-Connection-Request message
request := createSCCRMessage()
_, err = pptp.conn.Write(request)
if err != nil {
return zgrab2.TryGetScanStatus(err), &pptp.results, fmt.Errorf("error sending PPTP SCCR message: %w", err)
}

// Read the response
response, err := pptp.readResponse()
if err != nil {
return zgrab2.TryGetScanStatus(err), &pptp.results, fmt.Errorf("error reading PPTP response: %w", err)
}

// Store the banner and control message
pptp.results.Banner = string(request)
pptp.results.ControlMessage = response

return zgrab2.SCAN_SUCCESS, &pptp.results, nil
}
2 changes: 1 addition & 1 deletion zgrab2_schemas/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ you can follow these steps:
4. Pass in the zgrab2 JSON file to validate
* ```
echo 127.0.0.1 | ./cmd/zgrab2/zgrab2 mysql > output.json
PYTHONPATH=/path/to/zschema python2 -m zschema validate zgrab2 output.json --path . --module zgrab2_schemas.zgrab2
PYTHONPATH=/path/to/zschema python3 -m zschema validate zgrab2 output.json --path . --module zgrab2_schemas.zgrab2
```
## Adding new module schemas
Expand Down
1 change: 1 addition & 0 deletions zgrab2_schemas/zgrab2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
from . import ipp
from . import banner
from . import amqp091
from . import pptp
25 changes: 25 additions & 0 deletions zgrab2_schemas/zgrab2/pptp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# zschema sub-schema for zgrab2's PPTP module
# Registers zgrab2-pptp globally, and pptp with the main zgrab2 schema.
from zschema.leaves import *
from zschema.compounds import *
import zschema.registry

from . import zgrab2

# Schema for ScanResults struct
pptp_scan_response = SubRecord(
{
"banner": String(),
"control_message": String(),
}
)

pptp_scan = SubRecord(
{
"result": pptp_scan_response,
},
extends=zgrab2.base_scan_response,
)

zschema.registry.register_schema("zgrab2-pptp", pptp_scan)
zgrab2.register_scan_response_type("pptp", pptp_scan)

0 comments on commit 5780e09

Please sign in to comment.