Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenCTI CIRCL Hashlookup Enrichment Connector

Internal enrichment connector for OpenCTI that queries the CIRCL Hashlookup API to identify known/legitimate files from their hashes (MD5, SHA-1, SHA-256).

How it works

When a StixFile or Artifact observable is created or enriched in OpenCTI, the connector:

  1. Extracts the hash (SHA-256 > SHA-1 > MD5 by priority)
  2. Queries the CIRCL Hashlookup API (free, no API key required)
  3. If found, enriches the observable with:
    • 📝 STIX Note with file metadata (name, size, product, OS, trust)
    • 🔗 External reference to Hashlookup
    • 🏷️ Labels: known-good, hashlookup:<source_db>, hashlookup:<trust_level>
    • 📊 Adjusted score: a hash with high trust gets its OpenCTI score lowered

Databases queried

The CIRCL Hashlookup API aggregates multiple sources:

  • NSRL (National Software Reference Library) — Modern RDS, Legacy, Android, iOS
  • Windows 10/11 builds (FR, NL, DE, UK, US)
  • ~4.2 billion indexed hashes

Trust Level

The hashlookup:trust field ranges from 0 to 100:

Score Meaning
> 75 Well-known file, appears in multiple sources → hashlookup:high-trust
50-75 Known file with moderate confidence → hashlookup:medium-trust
< 50 Low confidence, needs verification → hashlookup:low-trust

The HASHLOOKUP_TRUST_THRESHOLD setting (default: 50) determines the minimum trust level required to apply the known-good label.

Installation

Docker (recommended)

Add to your OpenCTI docker-compose.yml:

connector-hashlookup:
  build: ./hashlookup-connector
  environment:
    - OPENCTI_URL=http://opencti:8080
    - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
    - CONNECTOR_ID=<uuid4>  # Generate with: python3 -c "import uuid; print(uuid.uuid4())"
    - CONNECTOR_TYPE=INTERNAL_ENRICHMENT
    - CONNECTOR_NAME=CIRCL Hashlookup
    - CONNECTOR_SCOPE=StixFile,Artifact
    - CONNECTOR_CONFIDENCE_LEVEL=80
    - CONNECTOR_LOG_LEVEL=info
    - CONNECTOR_AUTO=true
    - CONNECTOR_UPDATE_EXISTING_DATA=true
    - HASHLOOKUP_URL=https://hashlookup.circl.lu
    - HASHLOOKUP_TRUST_THRESHOLD=50
    - HASHLOOKUP_LABEL_KNOWN_GOOD=known-good
    - HASHLOOKUP_MAX_TLP=TLP:AMBER
  restart: always
  depends_on:
    - opencti

Standalone

cd hashlookup-connector
pip install -r requirements.txt
cp src/config.yml.sample src/config.yml
# Edit config.yml with your settings
cd src && python3 main.py

Configuration

Environment variable config.yml Description Default
OPENCTI_URL opencti.url OpenCTI instance URL (required)
OPENCTI_TOKEN opencti.token API token (required)
CONNECTOR_ID connector.id Connector UUID v4 (required)
CONNECTOR_AUTO connector.auto Auto-enrich on creation true
HASHLOOKUP_URL hashlookup.url Hashlookup API URL https://hashlookup.circl.lu
HASHLOOKUP_TRUST_THRESHOLD hashlookup.trust_threshold Min trust to label "known-good" 50
HASHLOOKUP_LABEL_KNOWN_GOOD hashlookup.label_known_good Label name for known files known-good
HASHLOOKUP_MAX_TLP hashlookup.max_tlp Max TLP for enrichment TLP:AMBER

Example result

After enriching a SHA-1 hash found in Hashlookup:

Note added:

CIRCL Hashlookup Match
- File: openssl
- Size: 723944 bytes
- Source DB: nsrl_modern_rds
- Trust Level: 100/100
- Product: OpenSSL 1.1.1
- MD5: 34D827A288FA51B93297EF2A8A43B769
- SHA-1: 72F104BF11A12511154267328F069FE0541E841E
- SHA-256: 301C9EC7A9AADEE4D745E8FD...

Labels: known-good, hashlookup:nsrl_modern_rds, hashlookup:high-trust

Score: lowered from 50 → 10

Private Hashlookup instance

If you don't want to send your lookups to the public CIRCL API, you can deploy your own instance:

  • hashlookup-server
  • A Bloom filter is also available for download (~700MB): https://cra.circl.lu/hashlookup/hashlookup-full.bloom

Simply change HASHLOOKUP_URL to point to your local instance.

License

MIT

About

Connector hashlookup for OpenCTI

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages