Skip to content

Instantly share code, notes, and snippets.

@nullenc0de
Created February 19, 2025 03:12
Show Gist options
  • Select an option

  • Save nullenc0de/a076a1a2ba01d7bedebf9ea57acf243f to your computer and use it in GitHub Desktop.

Select an option

Save nullenc0de/a076a1a2ba01d7bedebf9ea57acf243f to your computer and use it in GitHub Desktop.

Revisions

  1. nullenc0de created this gist Feb 19, 2025.
    226 changes: 226 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,226 @@
    #!/bin/bash

    # Colors for output
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    BLUE='\033[0;34m'
    NC='\033[0m'

    # Function to discover networks
    discover_networks() {
    echo "Discovering network segments..."
    declare -gA SEGMENTS

    # Read local routes
    while read -r line; do
    if [[ $line =~ ^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+) ]]; then
    network="${BASH_REMATCH[1]}"
    # Skip loopback and default routes
    if [[ $network != "127.0.0.0/8" && $network != "0.0.0.0/0" ]]; then
    # Try to determine segment type based on IP range
    if [[ $network == "10.152.10.0/24" ]]; then
    SEGMENTS["CDE"]=$network
    elif [[ $network == "192.168."* ]]; then
    SEGMENTS["DMZ"]=$network
    elif [[ $network == "10.191."* ]]; then
    if [[ $network == "10.191.10.0/24" ]]; then
    SEGMENTS["Corporate"]=$network
    elif [[ $network == "10.191.20.0/24" ]]; then
    SEGMENTS["Development"]=$network
    fi
    fi
    fi
    fi
    done < <(ip route show)

    echo "Discovered segments:"
    for segment in "${!SEGMENTS[@]}"; do
    echo " $segment: ${SEGMENTS[$segment]}"
    done
    }

    # Function to determine allowed paths based on common rules
    determine_allowed_paths() {
    echo "Determining allowed communication paths..."
    declare -ga ALLOWED_PATHS=()

    # Add standard paths based on best practices
    if [[ -n "${SEGMENTS[Corporate]}" && -n "${SEGMENTS[CDE]}" ]]; then
    ALLOWED_PATHS+=("Corporate:CDE:443") # HTTPS access to CDE
    fi

    if [[ -n "${SEGMENTS[DMZ]}" && -n "${SEGMENTS[CDE]}" ]]; then
    ALLOWED_PATHS+=("DMZ:CDE:443") # HTTPS access from DMZ to CDE
    fi

    if [[ -n "${SEGMENTS[Corporate]}" && -n "${SEGMENTS[DMZ]}" ]]; then
    ALLOWED_PATHS+=("Corporate:DMZ:80") # HTTP access to DMZ
    ALLOWED_PATHS+=("Corporate:DMZ:443") # HTTPS access to DMZ
    fi

    echo "Determined allowed paths:"
    for path in "${ALLOWED_PATHS[@]}"; do
    echo " $path"
    done
    }

    # Initialize network configuration
    discover_networks
    determine_allowed_paths

    # Allow manual override of detected configuration
    if [[ -f "network_config.txt" ]]; then
    echo "Found network_config.txt - loading manual configuration..."
    source network_config.txt
    fi

    # Define egress test ports
    declare -a TEST_PORTS=(
    "21" # FTP
    "22" # SSH
    "23" # Telnet
    "25" # SMTP
    "53" # DNS
    "80" # HTTP
    "443" # HTTPS
    "3389" # RDP
    "8080" # Alt HTTP
    "8443" # Alt HTTPS
    )

    # Test domains for egress
    EGRESS_TEST_DOMAIN="letmeoutofyour.net"
    RESPONSE_CHECK="w00tw00t"

    echo -e "${BLUE}Starting PCI DSS v4.0 Network Testing...${NC}"
    echo "Testing from IP: $(ip route get 1 | awk '{print $(NF-2);exit}')"
    echo "----------------------------------------"

    # Function to test TCP connectivity
    test_tcp() {
    local host=$1
    local port=$2
    timeout 2 nc -zv -w 2 $host $port &>/dev/null
    return $?
    }

    # Function to get a random IP from a subnet
    get_random_ip() {
    local subnet=$1
    local network=$(echo $subnet | cut -d/ -f1)
    local netmask=$(echo $subnet | cut -d/ -f2)
    local prefix=$(echo $network | cut -d. -f1-3)
    local random_last=$((RANDOM % 254 + 1))
    echo "${prefix}.${random_last}"
    }

    # Function to test egress connectivity
    test_egress() {
    local port=$1
    local protocol=$2
    echo -e "\n${YELLOW}Testing egress on port $port ($protocol)${NC}"

    case $protocol in
    "TCP")
    # Try HTTP/HTTPS connection
    if [[ $port == "80" || $port == "443" ]]; then
    response=$(curl -s -m 5 ${protocol,,}://$EGRESS_TEST_DOMAIN:$port 2>/dev/null)
    if [[ $response == *"$RESPONSE_CHECK"* ]]; then
    echo -e "${RED}WARNING: Egress allowed on port $port${NC}"
    return 0
    fi
    fi

    # Try direct TCP connection
    if nc -zv -w 5 $EGRESS_TEST_DOMAIN $port 2>/dev/null; then
    echo -e "${RED}WARNING: Egress allowed on port $port${NC}"
    return 0
    fi
    ;;
    "UDP")
    # Try UDP connection
    echo "Testing UDP..." | nc -u -w 5 $EGRESS_TEST_DOMAIN $port &>/dev/null
    if [[ $? -eq 0 ]]; then
    echo -e "${RED}WARNING: UDP egress allowed on port $port${NC}"
    return 0
    fi
    ;;
    esac

    echo -e "${GREEN}Egress blocked on port $port${NC}"
    return 1
    }

    echo -e "\n${BLUE}Phase 1: Testing Network Segmentation${NC}"
    # Test allowed paths
    for path in "${ALLOWED_PATHS[@]}"; do
    IFS=':' read -r source_seg dest_seg port <<< "$path"
    echo -e "\nTesting $source_seg to $dest_seg on port $port"

    source_ip=$(get_random_ip "${SEGMENTS[$source_seg]}")
    dest_ip=$(get_random_ip "${SEGMENTS[$dest_seg]}")

    if test_tcp $dest_ip $port; then
    echo -e "${GREEN}SUCCESS - Connection allowed as expected${NC}"
    else
    echo -e "${RED}FAIL - Expected connection blocked${NC}"
    fi
    done

    # Test segment isolation
    for source_seg in "${!SEGMENTS[@]}"; do
    for dest_seg in "${!SEGMENTS[@]}"; do
    if [ "$source_seg" != "$dest_seg" ]; then
    # Skip allowed paths
    skip=false
    for allowed in "${ALLOWED_PATHS[@]}"; do
    IFS=':' read -r as ds port <<< "$allowed"
    if [ "$source_seg" == "$as" ] && [ "$dest_seg" == "$ds" ]; then
    skip=true
    break
    fi
    done

    if [ "$skip" == "false" ]; then
    source_ip=$(get_random_ip "${SEGMENTS[$source_seg]}")
    dest_ip=$(get_random_ip "${SEGMENTS[$dest_seg]}")
    echo -e "\nTesting isolation between $source_seg and $dest_seg"

    for port in "${TEST_PORTS[@]}"; do
    if test_tcp $dest_ip $port; then
    echo -e "${RED}FAIL - Unexpected access allowed on port $port${NC}"
    else
    echo -e "${GREEN}SUCCESS - Connection blocked as expected on port $port${NC}"
    fi
    done
    fi
    fi
    done
    done

    echo -e "\n${BLUE}Phase 2: Testing Egress Controls${NC}"
    # Test egress using letmeoutofyour.net
    echo "Testing egress using $EGRESS_TEST_DOMAIN"

    # Test TCP ports
    for port in "${TEST_PORTS[@]}"; do
    test_egress $port "TCP"
    done

    # Test UDP ports
    for port in "${TEST_PORTS[@]}"; do
    test_egress $port "UDP"
    done

    # Test DNS exfiltration
    echo -e "\n${YELLOW}Testing DNS Exfiltration${NC}"
    if host "test.$EGRESS_TEST_DOMAIN" &>/dev/null; then
    echo -e "${RED}WARNING: DNS queries to external domains allowed${NC}"
    else
    echo -e "${GREEN}SUCCESS - DNS queries restricted${NC}"
    fi

    echo -e "\n${BLUE}Testing Complete${NC}"
    echo "Review results against network diagrams and PCI requirements"
    echo "Remember to test from multiple network segments for comprehensive coverage"