Skip to content

MISP Cheatsheet

MISP (Malware Information Sharing Platform) is an open-source threat intelligence platform designed to improve the sharing of structured threat information between organizations and communities.

Installation and Setup

bash
# Clone MISP Docker repository
git clone https://github.com/MISP/misp-docker.git
cd misp-docker

# Build and start MISP
docker-compose up -d

# Access MISP web interface
# URL: https://localhost
# Default credentials: admin@admin.test / admin

Ubuntu/Debian Installation

bash
# Update system
sudo apt update && sudo apt upgrade -y

# Install dependencies
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update

# Install required packages
sudo apt install -y python3.8 python3.8-dev python3.8-venv \
  apache2 mariadb-server libapache2-mod-php php php-cli \
  php-dev php-json php-mysql php-opcache php-readline \
  php-redis php-xml php-mbstring php-zip git

# Download MISP
cd /var/www
sudo git clone https://github.com/MISP/MISP.git
cd MISP
sudo git checkout tags/$(git describe --tags `git rev-list --tags --max-count=1`)
sudo git submodule update --init --recursive

CentOS/RHEL Installation

bash
# Install EPEL repository
sudo yum install -y epel-release

# Install dependencies
sudo yum install -y httpd mariadb-server php php-mysql php-mbstring \
  php-xml php-bcmath php-opcache git python3 python3-pip

# Start services
sudo systemctl start httpd mariadb
sudo systemctl enable httpd mariadb

# Clone MISP
cd /var/www/html
sudo git clone https://github.com/MISP/MISP.git

Database Setup

bash
# Secure MySQL installation
sudo mysql_secure_installation

# Create MISP database
sudo mysql -u root -p
sql
CREATE DATABASE misp;
CREATE USER 'misp'@'localhost' IDENTIFIED BY 'misp_password';
GRANT ALL PRIVILEGES ON misp.* TO 'misp'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Basic Configuration

Initial Setup

bash
# Set permissions
sudo chown -R www-data:www-data /var/www/MISP
sudo chmod -R 755 /var/www/MISP

# Copy configuration files
cd /var/www/MISP/app/Config
sudo cp bootstrap.default.php bootstrap.php
sudo cp database.default.php database.php
sudo cp core.default.php core.php
sudo cp config.default.php config.php

# Edit database configuration
sudo nano database.php

Database Configuration

php
<?php
class DATABASE_CONFIG {
    public $default = array(
        'datasource' => 'Database/Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'misp',
        'password' => 'misp_password',
        'database' => 'misp',
        'prefix' => '',
        'encoding' => 'utf8',
    );
}
?>

Apache Configuration

apache
# /etc/apache2/sites-available/misp.conf
<VirtualHost *:80>
    ServerName misp.local
    DocumentRoot /var/www/MISP/app/webroot
    
    <Directory /var/www/MISP/app/webroot>
        Options -Indexes
        AllowOverride all
        Require all granted
    </Directory>
    
    LogLevel warn
    ErrorLog /var/log/apache2/misp_error.log
    CustomLog /var/log/apache2/misp_access.log combined
    ServerSignature Off
</VirtualHost>
bash
# Enable site and modules
sudo a2ensite misp
sudo a2enmod rewrite
sudo systemctl restart apache2

Web Interface Usage

Initial Login

URL: http://your-misp-server
Default credentials:
- Username: admin@admin.test
- Password: admin

User Management

bash
# Create new user via CLI
cd /var/www/MISP/app/Console
sudo -u www-data ./cake User add [email] [org_id] [role_id]

# Change user password
sudo -u www-data ./cake User change_pw [email] [new_password]

# List users
sudo -u www-data ./cake User list

Organization Management

bash
# Add organization
sudo -u www-data ./cake Admin addOrg [org_name] [description] [type] [nationality]

# List organizations
sudo -u www-data ./cake Admin listOrgs

Event Management

Creating Events

python
# Using PyMISP library
from pymisp import PyMISP

misp = PyMISP('https://your-misp-server', 'your-api-key', ssl=False)

# Create new event
event = misp.new_event(
    distribution=1,
    threat_level_id=2,
    analysis=1,
    info="Malware Campaign Analysis"
)

print(f"Event created with ID: {event['Event']['id']}")

Adding Attributes

python
# Add IP attribute
misp.add_attribute(
    event['Event']['id'],
    type='ip-dst',
    value='192.168.1.100',
    category='Network activity',
    to_ids=True,
    comment='C2 Server IP'
)

# Add hash attribute
misp.add_attribute(
    event['Event']['id'],
    type='sha256',
    value='a1b2c3d4e5f6...',
    category='Payload delivery',
    to_ids=True,
    comment='Malware hash'
)

# Add domain attribute
misp.add_attribute(
    event['Event']['id'],
    type='domain',
    value='malicious-domain.com',
    category='Network activity',
    to_ids=True
)
python
# Search events by tag
events = misp.search(tags=['apt', 'malware'])

# Search by attribute value
events = misp.search(value='192.168.1.100')

# Search by date range
events = misp.search(
    date_from='2024-01-01',
    date_to='2024-01-31'
)

# Complex search
events = misp.search(
    org='Your Organization',
    tags=['apt'],
    category='Network activity',
    type_attribute='ip-dst'
)

API Usage

Authentication

bash
# Get API key from web interface: Administration -> List Auth Keys

# Test API connection
curl -H "Authorization: YOUR_API_KEY" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     https://your-misp-server/events/index

REST API Examples

bash
# Get all events
curl -H "Authorization: YOUR_API_KEY" \
     -H "Accept: application/json" \
     https://your-misp-server/events/index

# Get specific event
curl -H "Authorization: YOUR_API_KEY" \
     -H "Accept: application/json" \
     https://your-misp-server/events/view/1

# Create new event
curl -X POST \
     -H "Authorization: YOUR_API_KEY" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"Event":{"info":"Test Event","distribution":"1","threat_level_id":"2","analysis":"1"}}' \
     https://your-misp-server/events/add

# Add attribute to event
curl -X POST \
     -H "Authorization: YOUR_API_KEY" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"Attribute":{"type":"ip-dst","value":"192.168.1.1","category":"Network activity","to_ids":true}}' \
     https://your-misp-server/attributes/add/1

PyMISP Library

python
# Installation
pip install pymisp

# Basic usage
from pymisp import PyMISP

# Initialize connection
misp = PyMISP('https://your-misp-server', 'your-api-key', ssl=False)

# Test connection
print(misp.get_version())

# Get all events
events = misp.search(all=True)

# Get event by ID
event = misp.get_event(1)

# Search attributes
attributes = misp.search(
    controller='attributes',
    type_attribute='ip-dst',
    to_ids=True
)

Threat Intelligence Feeds

Feed Configuration

bash
# Enable feeds via web interface
# Administration -> List Feeds -> Add Feed

# Common feed URLs:
# - CIRCL OSINT Feed: https://www.circl.lu/doc/misp/feed-osint/
# - Botvrij.eu: https://www.botvrij.eu/data/feed-osint/
# - SURBL: https://feeds.surbl.org/

Feed Management

python
# List available feeds
feeds = misp.feeds()

# Enable feed
misp.enable_feed(feed_id=1)

# Fetch feed data
misp.fetch_feed(feed_id=1)

# Cache feed for faster access
misp.cache_feed(feed_id=1)

Custom Feed Creation

python
# Create custom feed
feed_data = {
    'Feed': {
        'name': 'Custom Threat Feed',
        'provider': 'Your Organization',
        'url': 'https://your-server.com/feed.json',
        'rules': '',
        'enabled': True,
        'distribution': 1,
        'sharing_group_id': 0,
        'tag_id': 0,
        'default': False,
        'source_format': 'misp',
        'fixed_event': False,
        'delta_merge': False,
        'event_id': 0,
        'publish': False,
        'override_ids': False,
        'settings': ''
    }
}

result = misp.add_feed(feed_data)

Automation and Integration

Automated Event Creation

python
#!/usr/bin/env python3
import json
from pymisp import PyMISP

def create_malware_event(iocs):
    misp = PyMISP('https://your-misp-server', 'your-api-key', ssl=False)
    
    # Create event
    event = misp.new_event(
        distribution=1,
        threat_level_id=2,
        analysis=1,
        info=f"Automated Malware Detection - {iocs['campaign']}"
    )
    
    event_id = event['Event']['id']
    
    # Add IOCs
    for ioc_type, values in iocs['indicators'].items():
        for value in values:
            misp.add_attribute(
                event_id,
                type=ioc_type,
                value=value,
                category='Payload delivery',
                to_ids=True,
                comment='Automated detection'
            )
    
    # Add tags
    for tag in iocs.get('tags', []):
        misp.tag(event['Event']['uuid'], tag)
    
    # Publish event
    misp.publish(event_id)
    
    return event_id

# Example usage
iocs = {
    'campaign': 'Banking Trojan Campaign',
    'indicators': {
        'ip-dst': ['192.168.1.100', '10.0.0.50'],
        'domain': ['malicious-site.com', 'evil-domain.net'],
        'sha256': ['a1b2c3d4e5f6...', 'f6e5d4c3b2a1...']
    },
    'tags': ['banking-trojan', 'apt', 'financial-sector']
}

event_id = create_malware_event(iocs)
print(f"Created event with ID: {event_id}")

SIEM Integration

python
# Splunk integration example
import requests
import json

def send_to_splunk(misp_event):
    splunk_url = 'https://your-splunk-server:8088/services/collector'
    splunk_token = 'your-hec-token'
    
    headers = {
        'Authorization': f'Splunk {splunk_token}',
        'Content-Type': 'application/json'
    }
    
    # Convert MISP event to Splunk format
    splunk_event = {
        'time': misp_event['Event']['timestamp'],
        'source': 'misp',
        'sourcetype': 'misp:event',
        'event': {
            'event_id': misp_event['Event']['id'],
            'info': misp_event['Event']['info'],
            'threat_level': misp_event['Event']['threat_level_id'],
            'attributes': misp_event['Event']['Attribute']
        }
    }
    
    response = requests.post(
        splunk_url,
        headers=headers,
        data=json.dumps(splunk_event),
        verify=False
    )
    
    return response.status_code == 200

Email Notifications

python
# Configure email notifications
def setup_email_notifications():
    # Via web interface: Administration -> Server Settings -> Email
    # Or via API:
    
    email_settings = {
        'MISP.email': 'admin@your-domain.com',
        'MISP.contact': 'admin@your-domain.com',
        'MISP.smtp_host': 'smtp.your-domain.com',
        'MISP.smtp_port': 587,
        'MISP.smtp_username': 'smtp-user',
        'MISP.smtp_password': 'smtp-password',
        'MISP.smtp_encryption': 'tls'
    }
    
    for setting, value in email_settings.items():
        misp.set_server_setting(setting, value)

Data Analysis and Visualization

Attribute Statistics

python
# Get attribute statistics
def get_attribute_stats():
    stats = misp.search(
        controller='attributes',
        return_format='json',
        limit=0
    )
    
    type_counts = {}
    category_counts = {}
    
    for attr in stats['Attribute']:
        attr_type = attr['type']
        category = attr['category']
        
        type_counts[attr_type] = type_counts.get(attr_type, 0) + 1
        category_counts[category] = category_counts.get(category, 0) + 1
    
    return {
        'types': type_counts,
        'categories': category_counts,
        'total': len(stats['Attribute'])
    }

stats = get_attribute_stats()
print(f"Total attributes: {stats['total']}")
print(f"Top types: {sorted(stats['types'].items(), key=lambda x: x[1], reverse=True)[:5]}")

Event Timeline

python
# Create event timeline
import matplotlib.pyplot as plt
from datetime import datetime

def create_event_timeline():
    events = misp.search(all=True)
    
    dates = []
    for event in events:
        timestamp = int(event['Event']['timestamp'])
        date = datetime.fromtimestamp(timestamp)
        dates.append(date)
    
    # Plot timeline
    plt.figure(figsize=(12, 6))
    plt.hist(dates, bins=30, alpha=0.7)
    plt.title('MISP Events Timeline')
    plt.xlabel('Date')
    plt.ylabel('Number of Events')
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.savefig('misp_timeline.png')
    plt.show()

IOC Correlation

python
# Find correlated IOCs
def find_correlations(ioc_value):
    # Search for the IOC
    results = misp.search(value=ioc_value)
    
    correlations = []
    for event in results:
        event_id = event['Event']['id']
        
        # Get all attributes from the same event
        full_event = misp.get_event(event_id)
        
        for attr in full_event['Event']['Attribute']:
            if attr['value'] != ioc_value:
                correlations.append({
                    'event_id': event_id,
                    'type': attr['type'],
                    'value': attr['value'],
                    'category': attr['category']
                })
    
    return correlations

# Example usage
correlations = find_correlations('192.168.1.100')
for corr in correlations[:10]:  # Show first 10
    print(f"Event {corr['event_id']}: {corr['type']} = {corr['value']}")

Security and Best Practices

Access Control

bash
# Role-based access control
# 1. Site Admin - Full access
# 2. Org Admin - Organization management
# 3. User - Basic event access
# 4. Publisher - Can publish events
# 5. Sync User - For synchronization

# Create role via CLI
sudo -u www-data ./cake Admin addRole [role_name] [permissions]

Data Encryption

bash
# Enable HTTPS
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d your-misp-domain.com

# Configure SSL in Apache
sudo nano /etc/apache2/sites-available/misp-ssl.conf
apache
<VirtualHost *:443>
    ServerName your-misp-domain.com
    DocumentRoot /var/www/MISP/app/webroot
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/your-misp-domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/your-misp-domain.com/privkey.pem
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options nosniff
    Header always set X-Frame-Options DENY
    Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>

Backup and Recovery

bash
# Database backup
mysqldump -u misp -p misp > misp_backup_$(date +%Y%m%d).sql

# File system backup
tar -czf misp_files_backup_$(date +%Y%m%d).tar.gz /var/www/MISP

# Automated backup script
#!/bin/bash
BACKUP_DIR="/backup/misp"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p $BACKUP_DIR

# Database backup
mysqldump -u misp -p misp > $BACKUP_DIR/misp_db_$DATE.sql

# Files backup
tar -czf $BACKUP_DIR/misp_files_$DATE.tar.gz /var/www/MISP

# Keep only last 7 days of backups
find $BACKUP_DIR -name "misp_*" -mtime +7 -delete

Troubleshooting

Common Issues

bash
# Check MISP logs
tail -f /var/www/MISP/app/tmp/logs/error.log
tail -f /var/www/MISP/app/tmp/logs/debug.log

# Check Apache logs
tail -f /var/log/apache2/misp_error.log
tail -f /var/log/apache2/misp_access.log

# Check database connectivity
mysql -u misp -p misp -e "SELECT COUNT(*) FROM events;"

# Check file permissions
ls -la /var/www/MISP/app/tmp/
ls -la /var/www/MISP/app/files/

Performance Optimization

bash
# MySQL optimization
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
ini
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connections = 200
query_cache_size = 64M
query_cache_limit = 2M
bash
# PHP optimization
sudo nano /etc/php/7.4/apache2/php.ini
ini
memory_limit = 512M
max_execution_time = 300
max_input_time = 300
post_max_size = 50M
upload_max_filesize = 50M

Diagnostic Commands

bash
# MISP diagnostic
cd /var/www/MISP/app/Console
sudo -u www-data ./cake Admin runUpdates
sudo -u www-data ./cake Admin setSetting "MISP.python_bin" "/usr/bin/python3"

# Check MISP status
sudo -u www-data ./cake Admin getSetting all

# Test email configuration
sudo -u www-data ./cake Email test [email@domain.com]

Integration Examples

Threat Hunting Integration

python
# Integration with threat hunting tools
def hunt_iocs_in_logs(misp_event_id):
    # Get IOCs from MISP event
    event = misp.get_event(misp_event_id)
    iocs = []
    
    for attr in event['Event']['Attribute']:
        if attr['to_ids']:
            iocs.append({
                'type': attr['type'],
                'value': attr['value']
            })
    
    # Search in log files (example with grep)
    import subprocess
    
    results = []
    for ioc in iocs:
        if ioc['type'] in ['ip-dst', 'ip-src']:
            cmd = f"grep -r '{ioc['value']}' /var/log/"
            try:
                output = subprocess.check_output(cmd, shell=True, text=True)
                if output:
                    results.append({
                        'ioc': ioc,
                        'matches': output.strip().split('\n')
                    })
            except subprocess.CalledProcessError:
                pass
    
    return results

YARA Rule Generation

python
# Generate YARA rules from MISP attributes
def generate_yara_rule(event_id):
    event = misp.get_event(event_id)
    
    rule_name = f"MISP_Event_{event_id}"
    rule_description = event['Event']['info']
    
    strings = []
    conditions = []
    
    for attr in event['Event']['Attribute']:
        if attr['type'] == 'sha256':
            strings.append(f'$hash_{len(strings)} = "{attr["value"]}"')
            conditions.append(f'$hash_{len(strings)-1}')
        elif attr['type'] in ['domain', 'hostname']:
            strings.append(f'$domain_{len(strings)} = "{attr["value"]}" nocase')
            conditions.append(f'$domain_{len(strings)-1}')
    
    yara_rule = f'''
rule {rule_name} {{
    meta:
        description = "{rule_description}"
        misp_event_id = "{event_id}"
        generated = "{datetime.now().isoformat()}"
    
    strings:
        {chr(10).join(strings)}
    
    condition:
        any of them
}}
'''
    
    return yara_rule

Resources