MISP Cheatsheet
MISP (logiciel malveillant Information Sharing Platform) is an open-source Renseignement sur les Menaces platform designed to improve the sharing of structured threat information between organizations and communities.
Installation and Setup
Docker Installation (Recommended)
# 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://localhôte
# Default identifiants: admin@admin.test / admin
Ubuntu/Debian Installation
# 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
# 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
# Secure MySQL Installation
sudo mysql_secure_Installation
# Create MISP database
sudo mysql -u root -p
CREATE DATABASE misp;
CREATE USER 'misp'@'localhôte' IDENTIFIED BY 'misp_mot de passe';
GRANT ALL PRIVILEGES ON misp.* TO 'misp'@'localhôte';
FLUSH PRIVILEGES;
EXIT;
Basic configuration
Initial Setup
# 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
class DATABASE_CONFIG \\\\{
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'hôte' => 'localhôte',
'login' => 'misp',
'mot de passe' => 'misp_mot de passe',
'database' => 'misp',
'prefix' => '',
'encoding' => 'utf8',
);
\\\\}
?>
Apache configuration
# /etc/apache2/sites-available/misp.conf
<Virtualhôte *: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
</Virtualhôte>
# Enable site and modules
sudo a2ensite misp
sudo a2enmod rewrite
sudo systemctl restart apache2
Web Interface utilisation
Initial Login
URL: http://your-misp-server
Default identifiants:
- nom d'utilisateur: admin@admin.test
- mot de passe: admin
User Management
# 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 mot de passe
sudo -u www-data ./cake User change_pw [email] [new_mot de passe]
# List users
sudo -u www-data ./cake User list
Organization Management
# 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
# Using PyMISP library
from pymisp import PyMISP
misp = PyMISP('https://your-misp-server', 'your-api-clé', ssl=False)
# Create new event
event = misp.new_event(
distribution=1,
threat_level_id=2,
analysis=1,
info="logiciel malveillant Campaign Analysis"
)
print(f"Event created with ID: \\\\{event['Event']['id']\\\\}")
Adding Attributes
# 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='charge utile delivery',
to_ids=True,
comment='logiciel malveillant hash'
)
# Add domain attribute
misp.add_attribute(
event['Event']['id'],
type='domain',
value='malicious-domain.com',
category='Network activity',
to_ids=True
)
Event Search
# Search events by tag
events = misp.search(tags=['apt', 'logiciel malveillant'])
# 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 utilisation
authentification
# Get API clé from web interface: Administration -> List Auth clés
# Test API connexion
curl -H "autorisation: YOUR_API_clé" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
https://your-misp-server/events/index
REST API exemples
# Get all events
curl -H "autorisation: YOUR_API_clé" \
-H "Accept: application/json" \
https://your-misp-server/events/index
# Get specific event
curl -H "autorisation: YOUR_API_clé" \
-H "Accept: application/json" \
https://your-misp-server/events/view/1
# Create new event
curl -X POST \
-H "autorisation: YOUR_API_clé" \
-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 "autorisation: YOUR_API_clé" \
-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
# Installation
pip install pymisp
# Basic utilisation
from pymisp import PyMISP
# Initialize connexion
misp = PyMISP('https://your-misp-server', 'your-api-clé', ssl=False)
# Test connexion
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
)
Renseignement sur les Menaces Feeds
Feed configuration
# 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
# 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
# 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
#!/usr/bin/env python3
import json
from pymisp import PyMISP
def create_logiciel malveillant_event(iocs):
misp = PyMISP('https://your-misp-server', 'your-api-clé', ssl=False)
# Create event
event = misp.new_event(
distribution=1,
threat_level_id=2,
analysis=1,
info=f"Automated logiciel malveillant 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='charge utile 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
# exemple utilisation
iocs = \\\\{
'campaign': 'Banking cheval de Troie Campaign',
'indicators': \\\\{
'ip-dst': ['192.168.1.100', '10.0.0.50'],
'domain': ['malicious-site.com', 'evil-domain.net'],
'sha256': ['a1b2c3d4e5f6...', 'f6e5d4c3b2a1...']
\\\\},
'tags': ['banking-cheval de Troie', 'apt', 'financial-sector']
\\\\}
event_id = create_logiciel malveillant_event(iocs)
print(f"Created event with ID: \\\\{event_id\\\\}")
SIEM Integration
# Splunk integration exemple
import requests
import json
def send_to_splunk(misp_event):
splunk_url = 'https://your-splunk-server:8088/services/collector'
splunk_jeton = 'your-hec-jeton'
headers = \\\\{
'autorisation': f'Splunk \\\\{splunk_jeton\\\\}',
'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
# 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_hôte': 'smtp.your-domain.com',
'MISP.smtp_port': 587,
'MISP.smtp_nom d'utilisateur': 'smtp-user',
'MISP.smtp_mot de passe': 'smtp-mot de passe',
'MISP.smtp_chiffrement': 'tls'
\\\\}
for setting, value in email_settings.items():
misp.set_server_setting(setting, value)
Data Analysis and Visualization
Attribute Statistics
# 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(), clé=lambda x: x[1], reverse=True)[:5]\\\\}")
Event Timeline
# 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
# 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
# exemple utilisation
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
Contrôle d'Accès
# Role-based Contrôle d'Accès
# 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 chiffrement
# 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
<Virtualhôte *:443>
ServerName your-misp-domain.com
DocumentRoot /var/www/MISP/app/webroot
SSLEngine on
SSLcertificatFile /etc/letsencrypt/live/your-misp-domain.com/fullchain.pem
SSLcertificatcléFile /etc/letsencrypt/live/your-misp-domain.com/privclé.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"
</Virtualhôte>
Backup and Recovery
# 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
dépannage
Common Issues
# 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
# MySQL optimization
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connexions = 200
query_cache_size = 64M
query_cache_limit = 2M
# PHP optimization
sudo nano /etc/php/7.4/apache2/php.ini
memory_limit = 512M
max_execution_time = 300
max_input_time = 300
post_max_size = 50M
upload_max_filesize = 50M
Diagnostic commandes
# 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 exemples
chasse aux menaces Integration
# Integration with chasse aux menaces 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 (exemple with grep)
import subprocessus
results = []
for ioc in iocs:
if ioc['type'] in ['ip-dst', 'ip-src']:
cmd = f"grep -r '\\\\{ioc['value']\\\\}' /var/log/"
try:
output = subprocessus.check_output(cmd, shell=True, text=True)
if output:
results.append(\\\\{
'ioc': ioc,
'matches': output.strip().split('\n')
\\\\})
except subprocessus.CalledprocessusError:
pass
return results
YARA Rule Generation
# 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', 'hôtename']:
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