Skip to content

πŸ›‘οΈ Type-safe security policy DSL parser with algebraic data types and pattern matching - OCaml

Notifications You must be signed in to change notification settings

bad-antics/nullsec-ocamlparse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 

Repository files navigation

NullSec OCamlParse

Security Policy Parser written in OCaml

Version Language License

Part of the NullSec offensive security toolkit
Discord: discord.gg/killers
Portal: bad-antics.github.io

Overview

OCamlParse is a type-safe security policy DSL parser and validator that processes firewall rules, validates configurations, and matches network packets against policies. Built with OCaml's algebraic data types, pattern matching, and functional composition.

OCaml Features Showcased

  • Algebraic Data Types: Variants and records
  • Pattern Matching: Exhaustive case analysis
  • Option/Result Types: Safe error handling
  • Modules: Encapsulated functionality
  • Higher-Order Functions: Functional composition
  • Type Inference: Concise, type-safe code
  • Immutable Data: Referential transparency

Policy DSL Features

Feature Syntax Description
IP Range SingleIP, CIDR, Range, AnyIP IP address specifications
Port Spec SinglePort, PortRange, PortList, AnyPort Port matching
Protocol TCP, UDP, ICMP, Any Protocol filtering
Direction Inbound, Outbound, Both Traffic direction
Action Allow, Deny, Log, Alert, Quarantine Rule actions

Installation

# Clone
git clone https://github.com/bad-antics/nullsec-ocamlparse.git
cd nullsec-ocamlparse

# Build with OCaml
ocamlfind ocamlopt -o ocamlparse ocamlparse.ml

# Or with Dune
dune build

# Run directly
ocaml ocamlparse.ml

Usage

# Run demo mode
./ocamlparse

# Parse policy file
./ocamlparse -f policy.json

# Validate only
./ocamlparse --validate policy.json

# Test packet matching
./ocamlparse --test packets.json -f policy.json

Options

USAGE:
    ocamlparse [OPTIONS]

OPTIONS:
    -f, --file       Policy file to parse
    --validate       Validate policy only
    --test           Test packet matching
    --json           JSON output format
    -v, --verbose    Verbose output

Sample Output

╔══════════════════════════════════════════════════════════════════╗
β•‘        NullSec OCamlParse - Security Policy Parser               β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

[Demo Mode]

Parsing and validating security policy...

βœ“ Policy is valid

═══════════════════════════════════════════════════════════════════
  Policy: Network Security Policy (v1.0.0)
  Default Action: DENY
  Rules: 7 (7 enabled)
═══════════════════════════════════════════════════════════════════

  [CRITICAL] Block Known C2 IPs
      ID:          NET-001
      Action:      DENY
      Status:      ENABLED
      MITRE:       T1071.001
      Conditions:  dst_ip=185.220.101.0/24, direction=OUTBOUND, protocol=TCP
      Description: Block outbound connections to known C2 infrastructure

  [HIGH] Block C2 Ports
      ID:          NET-002
      Action:      DENY
      Status:      ENABLED
      MITRE:       T1571
      Conditions:  dst_port=4444,5555,6666,31337, direction=OUTBOUND
      Description: Block connections to common C2 ports

  [LOW] Allow HTTPS
      ID:          NET-003
      Action:      ALLOW
      Status:      ENABLED
      MITRE:       N/A
      Conditions:  dst_port=443, protocol=TCP, direction=OUTBOUND
      Description: Allow outbound HTTPS traffic

═══════════════════════════════════════════════════════════════════

  Summary:
    Total Rules:  7
    Critical:     1
    High:         3
    Medium:       2
    Low:          1

Testing rule matching:

  192.168.1.100:54321 -> 185.220.101.45:443 (TCP): DENY [Block Known C2 IPs]
  192.168.1.100:55555 -> 8.8.8.8:4444 (TCP): DENY [Block C2 Ports]
  10.0.0.5:12345 -> 192.168.1.100:22 (TCP): LOG [Log SSH Connections]

═══════════════════════════════════════════════════════════════════

Code Highlights

Algebraic Data Types

type severity =
  | Critical
  | High
  | Medium
  | Low
  | Info

type ip_range =
  | SingleIP of string
  | CIDR of string * int
  | Range of string * string
  | AnyIP

type condition =
  | SourceIP of ip_range
  | DestIP of ip_range
  | SourcePort of port_spec
  | DestPort of port_spec
  | Protocol of protocol
  | Direction of direction
  | User of string
  | Process of string

Pattern Matching

let severity_to_string = function
  | Critical -> "CRITICAL"
  | High -> "HIGH"
  | Medium -> "MEDIUM"
  | Low -> "LOW"
  | Info -> "INFO"

let condition_matches packet = function
  | SourceIP range -> ip_in_range packet.src_ip range
  | DestIP range -> ip_in_range packet.dst_ip range
  | SourcePort spec -> port_matches packet.src_port spec
  | DestPort spec -> port_matches packet.dst_port spec
  | Protocol p -> packet.proto = p || p = Any
  | Direction d -> packet.dir = d || d = Both
  | User u -> packet.user = Some u
  | Process p -> packet.process_name = Some p

Result Type for Error Handling

type 'a result =
  | Ok of 'a
  | Error of parse_error

let ( >>= ) opt f = match opt with
  | Ok x -> f x
  | Error e -> Error e

let ( let* ) = ( >>= )

(* Usage with monadic binding *)
let* parsed = parse_policy input in
let* validated = validate_policy parsed in
return validated

Module-based Organization

module Validator = struct
  let validate_ip_range = function
    | SingleIP ip -> (* ... *)
    | CIDR (ip, mask) -> (* ... *)
    | Range (start_ip, end_ip) -> (* ... *)
    | AnyIP -> Valid
end

module Matcher = struct
  let rule_matches packet rule =
    rule.enabled && List.for_all (condition_matches packet) rule.conditions
  
  let get_action policy packet =
    match find_matching_rules policy packet with
    | [] -> policy.default_action
    | rule :: _ -> rule.action
end

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                OCamlParse Architecture                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚   β”‚  Policy Input    β”‚  (JSON, YAML, DSL)                     β”‚
β”‚   β”‚  (string)        β”‚                                        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚            β”‚                                                   β”‚
β”‚            β–Ό                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚   β”‚  Parser          β”‚  Algebraic Data Types                  β”‚
β”‚   β”‚  result type     β”‚  Pattern Matching                      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚            β”‚                                                   β”‚
β”‚            β–Ό                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚           Validator Module                        β”‚        β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚  β”‚ IP Range    β”‚ β”‚ Port Spec   β”‚ β”‚ Rule        β”‚ β”‚        β”‚
β”‚   β”‚  β”‚ Validation  β”‚ β”‚ Validation  β”‚ β”‚ Validation  β”‚ β”‚        β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β”‚            validation_result type                 β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                            β”‚                                   β”‚
β”‚                            β–Ό                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚           Matcher Module                          β”‚        β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚  β”‚ condition_  β”‚ β”‚ rule_       β”‚ β”‚ get_        β”‚ β”‚        β”‚
β”‚   β”‚  β”‚ matches     β”‚ β”‚ matches     β”‚ β”‚ action      β”‚ β”‚        β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β”‚            Exhaustive pattern matching            β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                            β”‚                                   β”‚
β”‚                            β–Ό                                   β”‚
β”‚                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚
β”‚                   β”‚  Report Module   β”‚                        β”‚
β”‚                   β”‚  format_policy   β”‚                        β”‚
β”‚                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why OCaml?

Requirement OCaml Advantage
Correctness Exhaustive pattern matching
Type Safety Strong static typing
Parsing Natural DSL representation
Performance Native code compilation
Maintainability Module system
Expressiveness Algebraic data types

License

MIT License - See LICENSE for details.

Related Tools

About

πŸ›‘οΈ Type-safe security policy DSL parser with algebraic data types and pattern matching - OCaml

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages