mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-13 19:05:17 +03:00
Add 10 new cybersecurity skills with full folder anatomy
Skills added: - implementing-privileged-access-workstation (IAM, PAW hardening) - detecting-suspicious-oauth-application-consent (cloud security, Graph API) - performing-hardware-security-module-integration (cryptography, PKCS#11) - analyzing-android-malware-with-apktool (malware analysis, androguard) - hunting-for-unusual-service-installations (threat hunting, T1543.003) - detecting-shadow-it-cloud-usage (cloud security, proxy/DNS log analysis) - performing-active-directory-forest-trust-attack (red team, impacket) - implementing-deception-based-detection-with-canarytoken (deception, Canary API) - analyzing-office365-audit-logs-for-compromise (cloud security, BEC detection) - hunting-for-startup-folder-persistence (threat hunting, T1547.001) Each skill includes SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Mahipal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: implementing-deception-based-detection-with-canarytoken
|
||||
description: Deploy and monitor Canary Tokens via the Thinkst Canary API for deception-based breach detection using web bug tokens, DNS tokens, document tokens, and AWS key tokens.
|
||||
domain: cybersecurity
|
||||
subdomain: deception-technology
|
||||
tags: [canarytoken, deception, honeytokens, breach-detection, Thinkst-Canary, tripwire, early-warning]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: Apache-2.0
|
||||
---
|
||||
|
||||
# Implementing Deception-Based Detection with Canarytoken
|
||||
|
||||
## Overview
|
||||
|
||||
Canary Tokens are lightweight tripwire mechanisms that alert when an attacker accesses a resource. This skill uses the Thinkst Canary REST API to programmatically create tokens (web bugs, DNS tokens, MS Word documents, AWS API keys), deploy them to strategic locations, monitor for triggered alerts, and generate deception coverage reports.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Thinkst Canary Console or canarytokens.org account
|
||||
- API auth token from Canary Console
|
||||
- Python 3.9+ with `requests`
|
||||
- File system access for deploying document and file tokens
|
||||
|
||||
## Steps
|
||||
|
||||
1. Authenticate to the Canary Console API using auth_token
|
||||
2. Create web bug (HTTP) tokens for embedding in documents and web pages
|
||||
3. Create DNS tokens for monitoring DNS resolution attempts
|
||||
4. Create MS Word document tokens for file share deployment
|
||||
5. List all active tokens and their trigger history
|
||||
6. Query recent alerts for triggered token events
|
||||
7. Generate deception coverage report with deployment recommendations
|
||||
|
||||
## Expected Output
|
||||
|
||||
- JSON report listing all deployed Canary Tokens, trigger history, alert details, and coverage analysis
|
||||
- Deployment map showing token types across network segments
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
# API Reference — Implementing Deception-Based Detection with Canarytoken
|
||||
|
||||
## Libraries Used
|
||||
- **requests**: HTTP client for Thinkst Canary Console REST API
|
||||
- **json**: JSON serialization for audit reports
|
||||
|
||||
## CLI Interface
|
||||
```
|
||||
python agent.py --console abc123 --auth-token TOKEN ping
|
||||
python agent.py --console abc123 --auth-token TOKEN list
|
||||
python agent.py --console abc123 --auth-token TOKEN alerts
|
||||
python agent.py --console abc123 --auth-token TOKEN create --kind http --memo "Web server token"
|
||||
python agent.py --console abc123 --auth-token TOKEN create --kind dns --memo "DNS honeypot"
|
||||
python agent.py --console abc123 --auth-token TOKEN coverage
|
||||
python agent.py --console abc123 --auth-token TOKEN full
|
||||
```
|
||||
|
||||
## Core Functions
|
||||
|
||||
### `CanaryClient(console_domain, auth_token)` — API client
|
||||
Base URL: `https://{console_domain}.canary.tools/api/v1`
|
||||
Auth: `auth_token` parameter on every request.
|
||||
|
||||
### `create_token(kind, memo, **kwargs)` — Create Canarytoken
|
||||
POST `/canarytoken/create` with `kind`, `memo`, `auth_token`.
|
||||
For doc-msword: uploads file via multipart form with MIME type
|
||||
`application/vnd.openxmlformats-officedocument.wordprocessingml.document`.
|
||||
|
||||
### `list_tokens()` — List all deployed tokens
|
||||
GET `/canarytokens/fetch`. Returns array of token objects with kind, memo, url, enabled.
|
||||
|
||||
### `get_alerts(newer_than)` — Fetch triggered token alerts
|
||||
GET `/incidents/all`. Optional `newer_than` timestamp filter.
|
||||
Returns src_host (source IP), description, timestamp, acknowledged status.
|
||||
|
||||
### `ack_alert(incident_id)` — Acknowledge an alert
|
||||
POST `/incident/acknowledge` with incident ID.
|
||||
|
||||
### `audit_token_coverage(client)` — Coverage analysis
|
||||
Calculates: tokens by kind, triggered vs untriggered, missing token types,
|
||||
coverage score as percentage of TOKEN_KINDS deployed.
|
||||
|
||||
### `full_audit(client)` — Comprehensive deception audit
|
||||
|
||||
## Canary Console API Endpoints
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/ping` | GET | Test API connectivity |
|
||||
| `/canarytoken/create` | POST | Create new token |
|
||||
| `/canarytokens/fetch` | GET | List all tokens |
|
||||
| `/canarytoken/fetch` | GET | Get specific token |
|
||||
| `/canarytoken/delete` | POST | Delete a token |
|
||||
| `/incidents/all` | GET | Fetch all alerts |
|
||||
| `/canarytoken/incidents` | GET | Alerts for specific token |
|
||||
| `/incident/acknowledge` | POST | Acknowledge alert |
|
||||
|
||||
## Supported Token Types
|
||||
| Kind | Description |
|
||||
|------|-------------|
|
||||
| http | Web bug — triggers on HTTP request |
|
||||
| dns | DNS token — triggers on DNS resolution |
|
||||
| doc-msword | MS Word document with embedded beacon |
|
||||
| pdf-acrobat-reader | PDF with embedded beacon |
|
||||
| aws-id | Fake AWS API key pair |
|
||||
| web-image | Image with tracking pixel |
|
||||
| cloned-web | Cloned website detection |
|
||||
| qr-code | QR code with tracking URL |
|
||||
| sensitive-cmd | Triggers on command execution |
|
||||
| windows-dir | Windows folder open detection |
|
||||
|
||||
## Dependencies
|
||||
- `requests` >= 2.28.0
|
||||
- Thinkst Canary Console account with API auth token
|
||||
@@ -0,0 +1,232 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for deploying and monitoring Canary Tokens via the Thinkst Canary API."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
requests = None
|
||||
|
||||
TOKEN_KINDS = {
|
||||
"http": "http",
|
||||
"dns": "dns",
|
||||
"doc-msword": "doc-msword",
|
||||
"pdf-acrobat-reader": "pdf-acrobat-reader",
|
||||
"web-image": "web-image",
|
||||
"cloned-web": "cloned-web",
|
||||
"aws-id": "aws-id",
|
||||
"qr-code": "qr-code",
|
||||
"sql": "sql",
|
||||
"svn": "svn",
|
||||
"smtp": "smtp",
|
||||
"windows-dir": "windows-dir",
|
||||
"sensitive-cmd": "sensitive-cmd",
|
||||
}
|
||||
|
||||
|
||||
class CanaryClient:
|
||||
"""Client for the Thinkst Canary Console REST API."""
|
||||
|
||||
def __init__(self, console_domain, auth_token):
|
||||
self.base_url = f"https://{console_domain}.canary.tools/api/v1"
|
||||
self.auth_token = auth_token
|
||||
|
||||
def _get(self, endpoint, params=None):
|
||||
params = params or {}
|
||||
params["auth_token"] = self.auth_token
|
||||
resp = requests.get(f"{self.base_url}{endpoint}", params=params, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def _post(self, endpoint, data=None, files=None):
|
||||
data = data or {}
|
||||
data["auth_token"] = self.auth_token
|
||||
resp = requests.post(f"{self.base_url}{endpoint}", data=data, files=files, timeout=30)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def ping(self):
|
||||
"""Test API connectivity."""
|
||||
return self._get("/ping")
|
||||
|
||||
def create_token(self, kind, memo, **kwargs):
|
||||
"""Create a new Canarytoken.
|
||||
|
||||
Args:
|
||||
kind: Token type (http, dns, doc-msword, aws-id, etc.)
|
||||
memo: Description/reminder for the token
|
||||
**kwargs: Additional parameters (e.g., cloned_web for cloned-web type)
|
||||
"""
|
||||
data = {"kind": kind, "memo": memo}
|
||||
data.update(kwargs)
|
||||
files = None
|
||||
if kind == "doc-msword" and "doc" in kwargs:
|
||||
doc_path = kwargs.pop("doc")
|
||||
data.pop("doc", None)
|
||||
files = {"doc": (doc_path, open(doc_path, "rb"),
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document")}
|
||||
return self._post("/canarytoken/create", data=data, files=files)
|
||||
|
||||
def list_tokens(self):
|
||||
"""List all Canarytokens on the console."""
|
||||
return self._get("/canarytokens/fetch")
|
||||
|
||||
def get_token(self, canarytoken):
|
||||
"""Get details for a specific token."""
|
||||
return self._get("/canarytoken/fetch", params={"canarytoken": canarytoken})
|
||||
|
||||
def delete_token(self, canarytoken):
|
||||
"""Delete a Canarytoken."""
|
||||
return self._post("/canarytoken/delete", data={"canarytoken": canarytoken})
|
||||
|
||||
def get_alerts(self, newer_than=None):
|
||||
"""Fetch recent alerts from triggered tokens."""
|
||||
params = {}
|
||||
if newer_than:
|
||||
params["newer_than"] = newer_than
|
||||
return self._get("/incidents/all", params=params)
|
||||
|
||||
def get_token_alerts(self, canarytoken):
|
||||
"""Fetch alerts for a specific token."""
|
||||
return self._get("/canarytoken/incidents", params={"canarytoken": canarytoken})
|
||||
|
||||
def ack_alert(self, incident_id):
|
||||
"""Acknowledge an alert."""
|
||||
return self._post("/incident/acknowledge", data={"incident": incident_id})
|
||||
|
||||
|
||||
def create_deployment(client, deployment_plan):
|
||||
"""Create multiple tokens based on a deployment plan."""
|
||||
results = []
|
||||
for token_spec in deployment_plan:
|
||||
kind = token_spec.get("kind", "http")
|
||||
memo = token_spec.get("memo", f"Canarytoken - {kind}")
|
||||
extra = {k: v for k, v in token_spec.items() if k not in ("kind", "memo")}
|
||||
try:
|
||||
resp = client.create_token(kind, memo, **extra)
|
||||
results.append({
|
||||
"kind": kind,
|
||||
"memo": memo,
|
||||
"status": "CREATED",
|
||||
"canarytoken": resp.get("canarytoken", {}).get("canarytoken", ""),
|
||||
"url": resp.get("canarytoken", {}).get("url", ""),
|
||||
})
|
||||
except Exception as e:
|
||||
results.append({"kind": kind, "memo": memo, "status": "FAILED", "error": str(e)})
|
||||
return results
|
||||
|
||||
|
||||
def audit_token_coverage(client):
|
||||
"""Audit deployed token coverage and generate report."""
|
||||
tokens_resp = client.list_tokens()
|
||||
tokens = tokens_resp.get("tokens", [])
|
||||
alerts_resp = client.get_alerts()
|
||||
alerts = alerts_resp.get("incidents", [])
|
||||
|
||||
kind_counts = {}
|
||||
triggered_tokens = set()
|
||||
for token in tokens:
|
||||
kind = token.get("kind", "unknown")
|
||||
kind_counts[kind] = kind_counts.get(kind, 0) + 1
|
||||
|
||||
for alert in alerts:
|
||||
triggered_tokens.add(alert.get("canarytoken", ""))
|
||||
|
||||
untriggered = [t for t in tokens if t.get("canarytoken", "") not in triggered_tokens]
|
||||
recommended_types = []
|
||||
for kind_name in TOKEN_KINDS:
|
||||
if kind_name not in kind_counts:
|
||||
recommended_types.append(kind_name)
|
||||
|
||||
return {
|
||||
"total_tokens": len(tokens),
|
||||
"total_alerts": len(alerts),
|
||||
"tokens_by_kind": kind_counts,
|
||||
"triggered_token_count": len(triggered_tokens),
|
||||
"untriggered_tokens": len(untriggered),
|
||||
"missing_token_types": recommended_types,
|
||||
"coverage_score": round(len(kind_counts) / len(TOKEN_KINDS) * 100, 1),
|
||||
}
|
||||
|
||||
|
||||
def full_audit(client):
|
||||
"""Run comprehensive Canarytoken deployment audit."""
|
||||
coverage = audit_token_coverage(client)
|
||||
tokens_resp = client.list_tokens()
|
||||
tokens = tokens_resp.get("tokens", [])
|
||||
alerts_resp = client.get_alerts()
|
||||
alerts = alerts_resp.get("incidents", [])
|
||||
|
||||
token_details = []
|
||||
for t in tokens[:30]:
|
||||
token_details.append({
|
||||
"canarytoken": t.get("canarytoken"),
|
||||
"kind": t.get("kind"),
|
||||
"memo": t.get("memo"),
|
||||
"created": t.get("created_printable"),
|
||||
"enabled": t.get("enabled"),
|
||||
"url": t.get("url", ""),
|
||||
})
|
||||
|
||||
alert_details = []
|
||||
for a in alerts[:20]:
|
||||
alert_details.append({
|
||||
"incident_id": a.get("id"),
|
||||
"description": a.get("description"),
|
||||
"source_ip": a.get("src_host"),
|
||||
"timestamp": a.get("created_printable"),
|
||||
"canarytoken": a.get("canarytoken"),
|
||||
"acknowledged": a.get("acknowledged"),
|
||||
})
|
||||
|
||||
return {
|
||||
"audit_type": "Canarytoken Deception Coverage Audit",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"coverage": coverage,
|
||||
"deployed_tokens": token_details,
|
||||
"recent_alerts": alert_details,
|
||||
"recommendation": "Deploy missing token types to improve coverage"
|
||||
if coverage["coverage_score"] < 50 else "Good coverage — review untriggered tokens",
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Canarytoken Deception Detection Agent")
|
||||
parser.add_argument("--console", required=True, help="Canary Console domain (e.g., abc123)")
|
||||
parser.add_argument("--auth-token", required=True, help="API auth token")
|
||||
sub = parser.add_subparsers(dest="command")
|
||||
sub.add_parser("ping", help="Test API connectivity")
|
||||
sub.add_parser("list", help="List all deployed tokens")
|
||||
sub.add_parser("alerts", help="Fetch recent alerts")
|
||||
p_create = sub.add_parser("create", help="Create a new token")
|
||||
p_create.add_argument("--kind", required=True, choices=list(TOKEN_KINDS.keys()))
|
||||
p_create.add_argument("--memo", required=True)
|
||||
sub.add_parser("coverage", help="Audit token coverage")
|
||||
sub.add_parser("full", help="Full deception audit")
|
||||
args = parser.parse_args()
|
||||
|
||||
client = CanaryClient(args.console, args.auth_token)
|
||||
|
||||
if args.command == "ping":
|
||||
result = client.ping()
|
||||
elif args.command == "list":
|
||||
result = client.list_tokens()
|
||||
elif args.command == "alerts":
|
||||
result = client.get_alerts()
|
||||
elif args.command == "create":
|
||||
result = client.create_token(args.kind, args.memo)
|
||||
elif args.command == "coverage":
|
||||
result = audit_token_coverage(client)
|
||||
elif args.command == "full" or args.command is None:
|
||||
result = full_audit(client)
|
||||
else:
|
||||
parser.print_help()
|
||||
return
|
||||
print(json.dumps(result, indent=2, default=str))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user