Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
galah — Galah: LLM 기반 웹 허니팟. | Kitploit
도구/GitHubGitHub/0x4d31/galah
Web SecurityThreat IntelligenceIntrusion DetectionIncident Response
GitHub0x4d31/galah

galah

Galah: LLM 기반 웹 허니팟.

저장소 보기
658661년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

TL;DR: Galah (/ɡəˈlɑː/ - ‘guh-laa’로 발음)는 LLM 기반 웹 허니팟으로, 다양한 애플리케이션을 모방하고 임의의 HTTP 요청에 동적으로 응답하도록 설계되었습니다. Galah는 OpenAI, GoogleAI, GCP의 Vertex AI, Anthropic, Cohere, Ollama 등 주요 LLM 제공업체를 지원합니다.

기존의 웹 허니팟이 특정 웹 애플리케이션이나 취약점을 수동으로 에뮬레이션하는 반면, Galah는 모든 HTTP 요청에 대해 HTTP 헤더와 본문 내용을 포함한 관련 응답을 동적으로 생성합니다. LLM이 생성한 응답은 구성 가능한 기간 동안 캐싱되어 동일한 요청에 대한 반복 생성을 방지하여 API 비용을 절감합니다. 캐싱은 포트별로 이루어지므로 특정 포트에서 생성된 응답이 다른 포트의 동일한 요청에 재사용되지 않습니다.

Galah는 선택적으로 들어오는 HTTP 요청을 Suricata 규칙 세트와 검사하여 메서드, URI, 헤더, 쿠키, 요청 본문 등 다양한 HTTP 버퍼와 일치시킬 수 있습니다 (현재 구현은 모든 Suricata 키워드를 지원하지 않으며 PCRE 처리는 제한적입니다). 규칙 일치를 활성화하고 구성하려면 Suricata HTTP 규칙 일치를 참조하세요.

프롬프트 구성은 이 허니팟의 핵심입니다. 구성 파일에서 프롬프트를 업데이트할 수 있지만, LLM이 지정된 JSON 형식으로 응답을 생성하도록 지시하는 부분을 유지하는 것이 중요합니다.

참고: Galah는 LLM이 HTTP 메시지를 생성하는 기능을 탐구하기 위해 재미있는 주말 프로젝트로 개발되었습니다. 이 허니팟은 네트워크 핑거프린팅 기술, LLM 제공업체 및 모델에 따른 긴 응답 시간, 비표준 응답 등 다양한 방법을 통해 식별될 수 있습니다. 지갑 고갈(Denial of Wallet) 공격을 방지하려면 LLM API에 사용량 한도를 반드시 설정하세요.

시작하기

로컬 배포

  • Go 버전 1.22+가 설치되어 있어야 합니다.
  • LLM 제공업체에 따라 API 키를 생성하거나 (예: OpenAI는 여기, GoogleAI Studio는 여기), 인증 자격 증명을 설정하세요 (예: GCP의 Vertex AI는 애플리케이션 기본 자격 증명).
  • HTTPS 포트를 제공하려면 TLS 인증서를 생성하세요.
  • 저장소를 클론하고 종속성을 설치하세요.
  • 필요한 경우 config.yaml 파일을 업데이트하세요.
  • Go 바이너리를 빌드하고 실행하세요!
root@kitploit:~
git clone [email protected]:0x4D31/galah.git
cd galah
go mod download
mkdir bin
go build -o bin/galah ./cmd/galah
./bin/galah --help

 ██████   █████  ██       █████  ██   ██ 
██       ██   ██ ██      ██   ██ ██   ██ 
██   ███ ███████ ██      ███████ ███████ 
██    ██ ██   ██ ██      ██   ██ ██   ██ 
 ██████  ██   ██ ███████ ██   ██ ██   ██ 
  llm-based web honeypot | version 1.1.1
         author: Adel "0x4D31" Ka

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] [--rules-config-file RULES-CONFIG-FILE] [--event-log-file EVENT-LOG-FILE] [--cache-db-file CACHE-DB-FILE] [--cache-duration CACHE-DURATION] [--log-level LOG-LEVEL] [--suricata-enabled] [--suricata-rules-dir SURICATA-RULES-DIR]

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]
  --rules-config-file RULES-CONFIG-FILE, -r RULES-CONFIG-FILE
                         Path to rules config file (rule engine disabled if omitted)
  --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]
  --suricata-enabled     Enable Suricata HTTP rule checking (default: false)
  --suricata-rules-dir SURICATA-RULES-DIR
                         Directory containing Suricata .rules files to check HTTP requests against
  --help, -h             display this help and exit

Docker에서 실행

  • Docker CE 또는 EE가 로컬에 설치되어 있어야 합니다.
  • 저장소를 클론하고 Docker 이미지를 빌드하세요.
  • 로그를 저장하기 위해 로컬 디렉토리를 컨테이너에 마운트할 수 있습니다.
  • Docker 컨테이너를 실행하세요.
root@kitploit:~
% git clone [email protected]: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

예제 사용법

root@kitploit:~
./galah -p openai -m gpt-4.1-mini --suricata-enabled --suricata-rules-dir rules

테스트:

root@kitploit:~
curl --http1.1 --path-as-is -X POST \
  -H 'SOAPAction: "http://purenetworks.com/HNAP1/GetGuestNetworkSettings"' \
  -H 'Content-Type: text/xml' \
  --data '<GetGuestNetworkSettings xmlns="http://purenetworks.com/HNAP1/">' \
  http://127.0.0.1:8888/HNAP1/ -v
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:8888...
* Connected to 127.0.0.1 (127.0.0.1) port 8888
> POST /HNAP1/ HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/8.7.1
> Accept: */*
> SOAPAction: "http://purenetworks.com/HNAP1/GetGuestNetworkSettings"
> Content-Type: text/xml
> Content-Length: 64
> 
* upload completely sent off: 64 bytes

< HTTP/1.1 200 OK
< Server: TP-LINK HTTP Server/1.0
< Date: Mon, 21 Apr 2025 01:28:43 GMT
< Content-Length: 545
< Content-Type: text/xml; charset=utf-8
< 
<?xml version="1.0" encoding="utf-8"?>
<GetGuestNetworkSettingsResponse xmlns="http://purenetworks.com/HNAP1/">
  <GetGuestNetworkSettingsResult>OK</GetGuestNetworkSettingsResult>
  <GuestNetworkEnabled>true</GuestNetworkEnabled>
  <GuestNetworkSSID>TPLink_Guest</GuestNetworkSSID>
  <GuestNetworkSecurity>WPA2-PSK</GuestNetworkSecurity>
  <GuestNetworkPassword>guest1234</GuestNetworkPassword>
  <GuestNetworkIsolation>true</GuestNetworkIsolation>
  <GuestNetworkSSIDBroadcast>true</GuestNetworkSSIDBroadcast>

JSON 이벤트 로그:

root@kitploit:~
{
  "eventTime": "2025-04-21T02:28:43.583386+01:00",
  "httpRequest": {
    "body": "<GetGuestNetworkSettings xmlns=\"http://purenetworks.com/HNAP1/\">",
    "bodySha256": "836c42168ebbad0b7192daa70ad8e4ea8d5930097162f513045f5ecb6ae9d5bd",
    "headers": {
      "Accept": "*/*",
      "Content-Length": "64",
      "Content-Type": "text/xml",
      "Soapaction": "\"http://purenetworks.com/HNAP1/GetGuestNetworkSettings\"",
      "User-Agent": "curl/8.7.1"
    },
    "headersSorted": "Accept,Content-Length,Content-Type,Soapaction,User-Agent",
    "headersSortedSha256": "3a44fecf9284eca3947c45ffeb2301ce6d9b3d0a3cc5a7491ccea2b6ed61edaa",
    "method": "POST",
    "protocolVersion": "HTTP/1.1",
    "request": "/HNAP1/",
    "sessionID": "1745198923587092000_qHLNEPBNPrH6qw==",
    "userAgent": "curl/8.7.1"
  },
  "httpResponse": {
    "headers": {
      "Content-Length": "454",
      "Content-Type": "text/xml; charset=utf-8",
      "Server": "TP-LINK HTTP Server/1.0"
    },
    "body": "<?xml version=\"1.0\" encoding=\"utf-8\"?> <GetGuestNetworkSettingsResponse xmlns=\"http://purenetworks.com/HNAP1/\">   <GetGuestNetworkSettingsResult>OK</GetGuestNetworkSettingsResult>   <GuestNetworkEnabled>true</GuestNetworkEnabled>   <GuestNetworkSSID>TPLink_Guest</GuestNetworkSSID>   <GuestNetworkSecurity>WPA2-PSK</GuestNetworkSecurity>   <GuestNetworkPassword>guest1234</GuestNetworkPassword>   <GuestNetworkIsolation>true</GuestNetworkIsolation>   <GuestNetworkSSIDBroadcast>true</GuestNetworkSSIDBroadcast> </GetGuestNetworkSettingsResponse>"
  },
  "level": "info",
  "msg": "successfulResponse",
  "port": "8888",
  "responseMetadata": {
    "generationSource": "llm",
    "info": {
      "model": "gpt-4.1-mini",
      "provider": "openai",
      "temperature": 1
    }
  },
  "sensorName": "mbp",
  "srcHost": "localhost",
  "srcIP": "127.0.0.1",
  "srcPort": "62418",
  "suricataMatches": [
    {
      "msg": "ET WEB_SPECIFIC_APPS D-Link DIR-823G Multiple HNAP SOAPAction Endpoints Authentication Bypass",
      "sid": "2061623"
    }
  ],
  "tags": null,
  "time": "2025-04-21T02:28:43.587152+01:00"
}

더 많은 예제는 여기에서 확인하세요.

라이브러리 사용법

galah 패키지는 독립형 라이브러리로 사용할 수 있습니다. galah.Service를 생성하고 GenerateHTTPResponse를 http.Request와 함께 호출하여 응답을 생성합니다. ConfigFile, EventLogFile 또는 CacheDBFile이 생략되면 기본 경로(config/config.yaml, event_log.json, cache.db)가 사용됩니다. RulesConfigFile을 지정하면 규칙 확인이 활성화되고, 비워두면 규칙 엔진이 완전히 비활성화됩니다. Options.Logger는 *log.Logger로 제공할 수 있으며, nil이면 Galah가 기본 텍스트 로거를 생성합니다.

root@kitploit:~
svc, err := galah.NewService(context.Background(), galah.Options{
    LLMProvider: "openai",
    LLMModel:    "gpt-4.1-mini",
    LLMAPIKey:   "YOUR_KEY",
    ConfigFile:  "config/config.yaml",
    RulesConfigFile: "config/rules.yaml", // omit to disable rule engine
    EventLogFile: "event_log.json",
    CacheDBFile:  "cache.db",
    Logger:       log.NewWithOptions(os.Stderr, log.Options{}),
})
if err != nil {
    log.Fatal(err)
}
req, _ := http.NewRequest("GET", "https://example.com", nil)
respBytes, err := svc.GenerateHTTPResponse(req, "8080")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(respBytes))

이미 로드된 구성으로 서비스를 빌드할 수도 있습니다:

root@kitploit:~
cfg, _ := config.LoadConfig("config.yaml")
rulesCfg, _ := config.LoadRules("rules.yaml")
svc, err := galah.NewServiceFromConfig(context.Background(), cfg, rulesCfg.Rules, galah.Options{
    LLMProvider: "openai",
    LLMModel:    "gpt-4.1-mini",
    LLMAPIKey:   "YOUR_KEY",
    EventLogFile: "event_log.json", // use default if empty
    CacheDBFile:  "cache.db",       // use default if empty
    Logger:       log.NewWithOptions(os.Stderr, log.Options{}),
})

규칙 확인을 완전히 비활성화하려면 서비스를 생성할 때 RulesConfigFile을 생략하거나 NewServiceFromConfig에 nil/빈 슬라이스를 전달하세요. 사용되지 않은 옵션 필드는 기본값에 의존하도록 비워둘 수 있습니다.

서비스는 라이브러리로 사용될 때 캐시 및 이벤트 로깅을 위한 헬퍼 메서드도 제공합니다:

root@kitploit:~
respBytes, _ := svc.CheckCache(req, "8080") // returns nil if no cached entry

svc.LogEvent(req, llm.JSONResponse{Headers: map[string]string{"Content-Type": "text/plain"}, Body: "hi"}, "8080", "llm", nil)
도구 다운로드