mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-03 01:10:18 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
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,65 @@
|
||||
# API Reference: Hunting for Webshell Activity
|
||||
|
||||
## Process Tree Detection
|
||||
|
||||
| Parent Process | Child Process | Severity |
|
||||
|----------------|---------------|----------|
|
||||
| w3wp.exe | cmd.exe, powershell.exe | CRITICAL |
|
||||
| httpd/apache2 | bash, sh, python | CRITICAL |
|
||||
| tomcat/java | cmd.exe, bash | CRITICAL |
|
||||
| nginx | bash, sh | CRITICAL |
|
||||
|
||||
## Splunk SPL - Web Server Shell Spawn
|
||||
|
||||
```spl
|
||||
index=sysmon EventCode=1
|
||||
| where match(ParentImage, "(?i)(w3wp|httpd|apache2|nginx|tomcat)")
|
||||
| where match(Image, "(?i)(cmd\.exe|powershell|bash|whoami|net\.exe)")
|
||||
| table _time Computer ParentImage Image CommandLine User
|
||||
```
|
||||
|
||||
## KQL - Web Shell Process Chain
|
||||
|
||||
```kql
|
||||
DeviceProcessEvents
|
||||
| where InitiatingProcessFileName in~ ("w3wp.exe", "httpd", "apache2", "nginx")
|
||||
| where FileName in~ ("cmd.exe", "powershell.exe", "bash", "whoami.exe")
|
||||
| project Timestamp, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine
|
||||
```
|
||||
|
||||
## Web Access Log Patterns
|
||||
|
||||
```python
|
||||
webshell_patterns = [
|
||||
r"POST\s+.*\.(asp|aspx|php|jsp)\s+", # POST to script files
|
||||
r"cmd=|exec=|command=|shell=", # Command parameters
|
||||
r"c99shell|r57shell|b374k|weevely", # Known webshell names
|
||||
]
|
||||
```
|
||||
|
||||
## Sigma Rule - Webshell Detection
|
||||
|
||||
```yaml
|
||||
title: Webshell Spawning Shell Process
|
||||
logsource:
|
||||
category: process_creation
|
||||
product: windows
|
||||
detection:
|
||||
parent:
|
||||
ParentImage|endswith: '\w3wp.exe'
|
||||
child:
|
||||
Image|endswith:
|
||||
- '\cmd.exe'
|
||||
- '\powershell.exe'
|
||||
condition: parent and child
|
||||
level: critical
|
||||
tags:
|
||||
- attack.persistence
|
||||
- attack.t1505.003
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- MITRE T1505.003: https://attack.mitre.org/techniques/T1505/003/
|
||||
- SANS Webshell Detection: https://www.sans.org/white-papers/
|
||||
- Sigma webshell rules: https://github.com/SigmaHQ/sigma
|
||||
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for hunting web shell activity on web servers via process tree and log analysis."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
WEB_SERVER_PROCESSES = [
|
||||
"w3wp.exe", "httpd", "apache2", "nginx", "tomcat", "java",
|
||||
"php-cgi", "php-fpm", "node", "iisexpress",
|
||||
]
|
||||
|
||||
SHELL_SPAWNS = [
|
||||
"cmd.exe", "powershell.exe", "pwsh.exe", "bash", "sh",
|
||||
"wscript.exe", "cscript.exe", "certutil.exe", "whoami.exe",
|
||||
"net.exe", "net1.exe", "ipconfig.exe", "systeminfo.exe",
|
||||
"tasklist.exe", "nslookup.exe",
|
||||
]
|
||||
|
||||
WEBSHELL_HTTP_PATTERNS = [
|
||||
r"POST\s+.*\.(asp|aspx|php|jsp|jspx)\s+",
|
||||
r"cmd=", r"exec=", r"command=", r"shell=",
|
||||
r"c99shell", r"r57shell", r"b374k", r"weevely",
|
||||
r"china\s*chopper", r"antsword",
|
||||
]
|
||||
|
||||
|
||||
def load_process_logs(log_path):
|
||||
"""Load process creation logs (JSON lines)."""
|
||||
entries = []
|
||||
with open(log_path) as f:
|
||||
for line in f:
|
||||
try:
|
||||
entries.append(json.loads(line))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
return entries
|
||||
|
||||
|
||||
def detect_webserver_child_shells(process_logs):
|
||||
"""Detect shell processes spawned by web server processes."""
|
||||
findings = []
|
||||
for entry in process_logs:
|
||||
parent = entry.get("ParentImage", entry.get("parent_process", "")).lower()
|
||||
child = entry.get("Image", entry.get("process_name", "")).lower()
|
||||
is_web_parent = any(ws in parent for ws in WEB_SERVER_PROCESSES)
|
||||
is_shell_child = any(sh in child for sh in SHELL_SPAWNS)
|
||||
if is_web_parent and is_shell_child:
|
||||
cmd = entry.get("CommandLine", entry.get("command_line", ""))
|
||||
findings.append({
|
||||
"timestamp": entry.get("UtcTime", entry.get("timestamp", "")),
|
||||
"hostname": entry.get("Computer", entry.get("hostname", "")),
|
||||
"parent_process": parent,
|
||||
"child_process": child,
|
||||
"command_line": cmd[:500],
|
||||
"user": entry.get("User", ""),
|
||||
"severity": "CRITICAL",
|
||||
"technique": "T1505.003",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def analyze_web_access_logs(access_log_path):
|
||||
"""Analyze web access logs for webshell indicators."""
|
||||
findings = []
|
||||
with open(access_log_path) as f:
|
||||
for i, line in enumerate(f, 1):
|
||||
for pattern in WEBSHELL_HTTP_PATTERNS:
|
||||
if re.search(pattern, line, re.IGNORECASE):
|
||||
ip_match = re.match(r"^(\S+)", line)
|
||||
findings.append({
|
||||
"line_number": i,
|
||||
"source_ip": ip_match.group(1) if ip_match else "",
|
||||
"log_entry": line.strip()[:500],
|
||||
"pattern_matched": pattern,
|
||||
"severity": "HIGH",
|
||||
})
|
||||
break
|
||||
return findings
|
||||
|
||||
|
||||
def detect_file_creation_in_webroot(file_events, webroot_paths=None):
|
||||
"""Detect new script files created in web server directories."""
|
||||
if webroot_paths is None:
|
||||
webroot_paths = [
|
||||
"/var/www", "/opt/lampp/htdocs", "inetpub/wwwroot",
|
||||
"/usr/share/nginx/html", "/srv/www",
|
||||
]
|
||||
script_extensions = [".php", ".asp", ".aspx", ".jsp", ".jspx", ".cgi", ".cfm"]
|
||||
findings = []
|
||||
for event in file_events:
|
||||
filepath = event.get("TargetFilename", event.get("file_path", "")).lower()
|
||||
in_webroot = any(wr in filepath for wr in webroot_paths)
|
||||
is_script = any(filepath.endswith(ext) for ext in script_extensions)
|
||||
if in_webroot and is_script:
|
||||
findings.append({
|
||||
"timestamp": event.get("UtcTime", event.get("timestamp", "")),
|
||||
"file_path": filepath,
|
||||
"process": event.get("Image", event.get("process_name", "")),
|
||||
"hostname": event.get("Computer", event.get("hostname", "")),
|
||||
"severity": "CRITICAL",
|
||||
"reason": "script_created_in_webroot",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def detect_post_exploitation(process_logs):
|
||||
"""Detect reconnaissance commands typically run through webshells."""
|
||||
recon_patterns = [
|
||||
(r"whoami", "user_discovery"),
|
||||
(r"ipconfig|ifconfig", "network_config"),
|
||||
(r"net\s+(user|group|localgroup)", "account_enum"),
|
||||
(r"systeminfo", "system_info"),
|
||||
(r"tasklist|ps\s+aux", "process_enum"),
|
||||
(r"netstat\s+-an", "connection_enum"),
|
||||
(r"dir\s+/s|find\s+/|ls\s+-la", "file_enum"),
|
||||
]
|
||||
findings = []
|
||||
for entry in process_logs:
|
||||
parent = entry.get("ParentImage", entry.get("parent_process", "")).lower()
|
||||
if not any(ws in parent for ws in WEB_SERVER_PROCESSES):
|
||||
continue
|
||||
cmd = entry.get("CommandLine", entry.get("command_line", ""))
|
||||
for pattern, category in recon_patterns:
|
||||
if re.search(pattern, cmd, re.IGNORECASE):
|
||||
findings.append({
|
||||
"timestamp": entry.get("UtcTime", entry.get("timestamp", "")),
|
||||
"command": cmd[:300],
|
||||
"category": category,
|
||||
"parent": parent,
|
||||
"severity": "HIGH",
|
||||
})
|
||||
break
|
||||
return findings
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Webshell Activity Hunter")
|
||||
parser.add_argument("--process-log", help="JSON lines process creation log")
|
||||
parser.add_argument("--access-log", help="Web server access log")
|
||||
parser.add_argument("--file-events", help="JSON lines file creation events")
|
||||
parser.add_argument("--output", default="webshell_hunt_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}
|
||||
|
||||
if args.process_log:
|
||||
logs = load_process_logs(args.process_log)
|
||||
shells = detect_webserver_child_shells(logs)
|
||||
report["findings"]["shell_spawns"] = shells
|
||||
print(f"[+] Web server shell spawns: {len(shells)}")
|
||||
recon = detect_post_exploitation(logs)
|
||||
report["findings"]["post_exploitation"] = recon
|
||||
print(f"[+] Post-exploitation commands: {len(recon)}")
|
||||
|
||||
if args.access_log:
|
||||
hits = analyze_web_access_logs(args.access_log)
|
||||
report["findings"]["access_log_hits"] = hits
|
||||
print(f"[+] Access log webshell indicators: {len(hits)}")
|
||||
|
||||
if args.file_events:
|
||||
events = load_process_logs(args.file_events)
|
||||
files = detect_file_creation_in_webroot(events)
|
||||
report["findings"]["webroot_files"] = files
|
||||
print(f"[+] Scripts created in webroot: {len(files)}")
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(f"[+] Report saved to {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user