CameraObscura - IP Cam Honeypot
IP Cameras are often misused for wide range malware campaigns. The purpose of this project is to fake a IP Camera with the common features, such as camera stream, login or firmware upload to protocolize actions done by botnets.
This project is currently under development. Most of the features are not implemented yet.
For God's sake, don't deploy this to productive environments. It's an honeypot which also could be exploited.
The honeypot basically serves routes to files with different logic between them.
In this (very unsafe) example, the login form uses a javascript to fetch the API /api/login and just checks for the response, if "ok" or "not okay" was returned. Afterwards, the script redirects the user /admin.html
/*
Successful login: login.html+login.js -[HTTP POST]-> /api/login -> index.html
Failed login: login.html+login.js -[HTTP POST]-> /api/login -> login.html
*/
templates/
mytemplate/
/index.html
/login.html
/admin.html
/login.js
/login_ok.txt
/login_fail.txt
/routes.json
- The first matched route is executed
- Within a route, the actions are executed in the order configured
{
"": { /* This just serves the index.html and can be extended with a redundant block with a key "index.html" */
"actions": [
"sleep",
"servefile",
],
"sleep": {
"duration": 2
},
"servefile": {
"file": "templates/mytemplate/index.html", /* Templates are always relative from the root directory */
"process_template": true /* If the file should be handled as a Jinja2 template? */
"process_placeholders": false /* If placeholders should be replaced */
}
},
"login.html": {
"actions": [
"sleep",
"servefile",
],
"sleep": {
"duration": 2
},
"servefile": {
"file": "templates/mytemplate/login.html",
"process_template": true
}
},
"/api/login": {
"actions": [
"sleep",
"authorize",
"servefile",
],
"sleep": {
"duration": 2
},
"servefile": {
/* This is the result if the authorize step succeeds */
"file": "templates/mytemplate/login_ok.txt",
"process_template": false
},
"authorize": {
"key_username": "usr", /* The key to search for inside of POST and GET dictionaries */
"key_password": "pwd", /* The key to search for inside of POST and GET dictionaries */
"user_db": "userdb.txt", /* A CSV containing the wanted username password combinations */
/* Can be either: Status Code (int) or String.
* When a string, it's either a template file or a route key to redirect to
*/
"on_error": "templates/mytemplate/login_fail.txt",
"on_error_placeholder": true /* If true, placeholders will be replaced in the file output */
"on_error_process_template": false /* Is the file to be handled as a template? */
},
},
"admin.html": {
"actions": [
"sleep",
"servefile",
],
"sleep": {
"duration": 2
},
"servefile": {
"file": "templates/mytemplate/admin.html",
"process_template": true
}
},
"cgi-bin/video.pl": {
"actions": [
"video"
],
"video": {
"video": "ul/video.mp4",
"mode": "m3u8"
},
"headers": {
"Content-Type": "application/x-mpegURL",
"Server": "lighttpd"
}
},
"cgi-bin/video(.+).ts": {
"actions": [
"servefile"
],
"servefile": {
"file": [
"ul/video$1.ts"
]
},
"headers": {
"Server": "lighttpd"
}
}
}
authorize Check user and password attempts and trigger actions
key_username: A key to search in GET and POST for the usernamekey_password: A key to search in GET and POST for the passworduser_db: The (relative) path to the user database, which is a CSV. Seeuserdb.txtas an exampleon_error: What to do on login error. Can be a status code or a string. If set to a string, it can either represent a template path to display or a route key to redirect to.on_error_placeholder: If the user cannot login andon_erroris set to a file: Seeservefile.process_placeholderson_error_process_templates: If the user cannot login andon_erroris set to a file: Seeservefile.process_template
servefile Serve a static file
file: Can be a file or array of files. If set to an array of files, a random file will be picked at runtimeprocess_template: if the file should be handled like a template (uses Jinja2)process_placeholders: if placeholders should be replaced. Placeholders are eitherstrftime()date and time placeholder (e. g.%Y) or values from the configuration, e. g.$honeypot.model. Please note that date time values are prefixed with a%while config values are using a$watermark: Must be a dictionary, containing (x: int, y: int, colors: [r,g,b], text: str). Text can use the same placeholder values as described inprocess_placeholders
sleep Delay actions
duration: A float duration on how many seconds should following modules wait to simulate poor hardware performancerandomize: If set to true, a random offset will be added to the duration value, following the formula:duration/randint(1,10)
catchfile Persists an uploaded file
- No further option
video Streams a video
This module requires ffmpeg
video: A video file to stream tomode: The video mode to stream to. Currently supported:m3u8.
Note: If you stream a video as a m3u8, you need to serve the output files aswell. For example, if your file isvideo.mp4, you need to add a route forul/video$1.tsaswell. See the routes example above for details.
Copy configuration.cfg.dist to configuration.cfg.
| Section and Key | Remarks |
|---|---|
honeypot.{hostname,firmware,serial,model,name,timezone} |
Fake values to inject into templates. Can be extended by own values |
honeypot.sensor |
Sensor name for logs |
honeypot.downloadDir |
The directory where to drop files into. Must be created before usage |
honeypot.debug |
Debug mode. Please keep to false. The debug mode will randomize IP addresses for testing purposes. |
log.path |
The path to the logfile |
log.timespan |
The duration to wait until rotating the logfile |
log.stdout |
If data should be logged into stdout aswell |
webhook.target |
The target URL of a single webhook to execute. If empty, the webhook wil be omitted |
webhook.flavour |
The webhook module to execute. Can be: core.webhooks.discord.Discord |
webhook.exclude |
Log messages to execute, commma separated list of event Id's (taken from logging.py) |
http.port |
The HTTP port to bind to |
http.host |
The HTTP host to bind to |
http.template |
The template to use. It's a folder name inside of the /templates folder |
- Fake Camera Endpoint (for HTTP
POST/GETetc.)- Fake camera stream
- JSON configurable Routes to simulate logins or upload of new firmware according to the specifications of the manufacturers
- Configurable headers to simulate a vulnerable webserver
- Web Interface
- Semi-Fake Web UI
- Clone existing to simulate running vulnerable IP-Cams
- Logging
- stdout
- JSON
- Payload dump (e. g. on fake firmware upload or
POSTwithfile)
- Webhook
- Discord
- Fake other services (like RTSP)
- Video Stream: RTSP
- Video Stream: M3U8
- SSH/ Telnet (using cowrie)
- Configuration
- Company Logos (via config/templates)
- Service/ Port redirect
- Routes
- Deployment/ Analysis/ Usage
- Docker Image
Python3
ffmpeg (for video module)
- Don't run the honeypot as root
- Don't run the honeypot on a productive environment
- Use a dedicated, isolated environment (like
qemu,lxd,lxcordocker) - It's still in development :)
Image: https://commons.wikimedia.org/wiki/Category:Camera_obscura#/media/File:001_a01_camera_obscura_abrazolas.jpg, Public Domain
MPL-2.0
