/galah

Galah: An LLM-powered web honeypot. Wasting attackers' time with faker-than-ever HTTP responses!

Primary LanguageGoApache License 2.0Apache-2.0

TL;DR: Galah (/ɡəˈlɑː/ - pronounced ‘guh-laa’) is an LLM-powered web honeypot designed to mimic various applications and dynamically respond to arbitrary HTTP requests. Galah supports major LLM providers, including OpenAI, GoogleAI, GCP's Vertex AI, Anthropic, Cohere, and Ollama.

Unlike traditional web honeypots that manually emulate specific web applications or vulnerabilities, Galah dynamically crafts relevant responses—including HTTP headers and body content—to any HTTP request. Responses generated by the LLM are cached for a configurable period to prevent repetitive generation for identical requests, reducing API costs. The caching is port-specific, ensuring that responses generated for a particular port will not be reused for the same request on a different port.

The prompt configuration is key in this honeypot. While you can update the prompt in the configuration file, it is crucial to maintain the segment directing the LLM to produce responses in the specified JSON format.

Note: Galah was developed as a fun weekend project to explore the capabilities of LLMs in crafting HTTP messages and is not intended for production use. The honeypot may be identifiable through various methods such as network fingerprinting techniques, prolonged response times depending on the LLM provider and model, and non-standard responses. To protect against Denial of Wallet attacks, be sure to set usage limits on your LLM API.

Getting Started

Local Deployment

  • Ensure you have Go version 1.22+ installed.
  • Depending on your LLM provider, create an API key (e.g., from here for OpenAI and here for GoogleAI Studio) or set up authentication credentials (e.g., Application Default Credentials for GCP's Vertex AI).
  • If you want to serve HTTPS ports, generate TLS certificates.
  • Clone the repo and install the dependencies.
  • Update the config.yaml file if needed.
  • Build and run the Go binary!
% git clone git@github.com:0x4D31/galah.git
% cd galah
% go mod download
% go build -o galah ./cmd/galah
% export LLM_API_KEY=your-api-key
% ./galah --help

 ██████   █████  ██       █████  ██   ██ 
██       ██   ██ ██      ██   ██ ██   ██ 
██   ███ ███████ ██      ███████ ███████ 
██    ██ ██   ██ ██      ██   ██ ██   ██ 
 ██████  ██   ██ ███████ ██   ██ ██   ██ 
  llm-based web honeypot // version 1.0
        author: Adel "0x4D31" Karimi

Usage: galah --provider PROVIDER --model MODEL [--server-url SERVER-URL] [--temperature TEMPERATURE] [--api-key API-KEY] [--cloud-location CLOUD-LOCATION] [--cloud-project CLOUD-PROJECT] [--interface INTERFACE] [--config-file CONFIG-FILE] [--event-log-file EVENT-LOG-FILE] [--cache-db-file CACHE-DB-FILE] [--cache-duration CACHE-DURATION] [--log-level LOG-LEVEL]

Options:
  --provider PROVIDER, -p PROVIDER
                         LLM provider (openai, googleai, gcp-vertex, anthropic, cohere, ollama) [env: LLM_PROVIDER]
  --model MODEL, -m MODEL
                         LLM model (e.g. gpt-3.5-turbo-1106, gemini-1.5-pro-preview-0409) [env: LLM_MODEL]
  --server-url SERVER-URL, -u SERVER-URL
                         LLM Server URL (required for Ollama) [env: LLM_SERVER_URL]
  --temperature TEMPERATURE, -t TEMPERATURE
                         LLM sampling temperature (0-2). Higher values make the output more random [default: 1, env: LLM_TEMPERATURE]
  --api-key API-KEY, -k API-KEY
                         LLM API Key [env: LLM_API_KEY]
  --cloud-location CLOUD-LOCATION
                         LLM cloud location region (required for GCP's Vertex AI) [env: LLM_CLOUD_LOCATION]
  --cloud-project CLOUD-PROJECT
                         LLM cloud project ID (required for GCP's Vertex AI) [env: LLM_CLOUD_PROJECT]
  --interface INTERFACE, -i INTERFACE
                         interface to serve on
  --config-file CONFIG-FILE, -c CONFIG-FILE
                         Path to config file [default: config/config.yaml]
  --event-log-file EVENT-LOG-FILE, -o EVENT-LOG-FILE
                         Path to event log file [default: event_log.json]
  --cache-db-file CACHE-DB-FILE, -f CACHE-DB-FILE
                         Path to database file for response caching [default: cache.db]
  --cache-duration CACHE-DURATION, -d CACHE-DURATION
                         Cache duration for generated responses (in hours). Use 0 to disable caching, and -1 for unlimited caching (no expiration). [default: 24]
  --log-level LOG-LEVEL, -l LOG-LEVEL
                         Log level (debug, info, error, fatal) [default: info]
  --help, -h             display this help and exit

Run in Docker

  • Ensure you have Docker CE or EE installed locally.
  • Clone the repo and build the docker image.
  • You can mount a local directory to the container to store the logs.
  • Run the docker container.
% git clone git@github.com:0x4D31/galah.git
% cd galah
% mkdir logs
% export LLM_API_KEY=your-api-key
% docker build -t galah-image .
% docker run -d --name galah-container -p 8080:8080 -v $(pwd)/logs:/galah/logs -e LLM_API_KEY galah-image -o logs/galah.json -p openai -m gpt-3.5-turbo-1106

Example Usage

./galah -p gcp-vertex -m gemini-1.0-pro-002 --cloud-project galah-test --cloud-location us-central1 --temperature 0.2 --cache-duration 0
% curl -i http://localhost:8080/.aws/credentials
HTTP/1.1 200 OK
Date: Sun, 26 May 2024 16:37:26 GMT
Content-Length: 116
Content-Type: text/plain; charset=utf-8

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

JSON event log:

{
  "eventTime": "2024-05-26T18:37:26.742418+02:00",
  "httpRequest": {
    "body": "",
    "bodySha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "headers": "User-Agent: [curl/7.71.1], Accept: [*/*]",
    "headersSorted": "Accept,User-Agent",
    "headersSortedSha256": "cf69e186169279bd51769f29d122b07f1f9b7e51bf119c340b66fbd2a1128bc9",
    "method": "GET",
    "protocolVersion": "HTTP/1.1",
    "request": "/.aws/credentials",
    "userAgent": "curl/7.71.1"
  },
  "httpResponse": {
    "headers": {
      "Content-Length": "127",
      "Content-Type": "text/plain"
    },
    "body": "[default]\naws_access_key_id = AKIAIOSFODNN7EXAMPLE\naws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n"
  },
  "level": "info",
  "llm": {
    "model": "gemini-1.0-pro-002",
    "provider": "gcp-vertex",
    "temperature": 0.2
  },
  "msg": "successfulResponse",
  "port": "8080",
  "sensorName": "mbp.local",
  "srcHost": "localhost",
  "srcIP": "::1",
  "srcPort": "51725",
  "tags": null,
  "time": "2024-05-26T18:37:26.742447+02:00"
}

See more examples here.