The Silent Push CLI is a powerful tool that allows you to interact directly with the Silent Push API from your terminal. It supports scoring, enriching, and querying DNS records for indicators of compromise (IOCs), such as domains and IP addresses. This guide covers installation, basic usage, advanced features, scripting, and development extensions.
Installation
To get started, download the Python wheel from the Silent Push Labs repository and install it using pip:
python3 -m pip install SilentPushCLI-0.0.1-py3-none-linux.whlAfter installation, set your Silent Push API key as an environment variable:
export SILENT_PUSH_API_KEY=YOUR-API-KEYReplace YOUR-API-KEY with your actual API key.
Usage
The CLI follows this syntax:
sp COMMAND [SUB-COMMAND...] IOC [PARAMETER=VALUE...] [OPTION...]Examples
Score a single domain:
sp score ig.comEnrich a domain with explanations:
sp enrich ig.com -esBulk enrich multiple domains:
sp bulk_enrich ig.com x.com ibm.com -esQuery DNS records:
sp padns query a ig.com limit=2 sort=last_seen/-Supported commands and sub-commands
The CLI currently supports the following commands and sub-commands:
Main commands
score: Calculate risk scores for IOCs.enrich: Enrich a single IOC with additional data.bulk_enrich: Enrich multiple IOCs in batch.padns: Query Passive DNS records (see sub-commands below).load: Load a command context (e.g.,load padns).unload: Unload the current command context.
PADNS sub-commands
Query types
query: General DNS query.any: Query any record type.anyipv4: Query IPv4 records.anyipv6: Query IPv6 records.a: Query A records.aaaa: Query AAAA records.cname: Query CNAME records.mx: Query MX records.ns: Query NS records.ptr4: Query PTR records for IPv4.ptr6: Query PTR records for IPv6.soa: Query SOA records.txt: Query TXT records.
Answer types
answer: Reverse lookup for answers.a: A record answers.aaaa: AAAA record answers.cname: CNAME record answers.mx: MX record answers.mxhash: MX hash answers.ns: NS record answers.nshash: NS hash answers.ptr4: PTR4 record answers.ptr6: PTR6 record answers.soa: SOA Record answers.soahash: SOA hash answers.txt: TXT record answers.txthash: TXT hash answers.
Options
Options can be applied to most commands to customize the output.
Global options (all commands)
-j, --json: Output in JSON format (default).-c, --csv: Output in CSV format.-t, --tsv: Output in TSV format.-h, --help: Display help for the command.
Enrich/Bulk Enrich specific options
-e, --explain: Include details on data used for score calculations.-s, --scan_data: Include Host scanning data details.
Interactive Mode
Launch the interactive console by running sp without arguments. This enters the sp console, where you can execute commands without the sp prefix.
Example session
SP# score ig.com
{
"domain": "ig.com",
"sp_risk_score": 18,
"sp_risk_score_explain": {
"sp_risk_score_decider": "ns_reputation_score"
}
}
SP# padns query a ig.com limit=1
{
"records": [
{
"answer": "195.234.39.132",
"count": 2681,
"first_seen": "2021-04-17 03:47:18",
"last_seen": "2024-08-16 12:11:22",
"query": "ig.com",
"type": "A"
}
]
}
SP#Load and Unload Commands
Use load to switch to a specific command context, loading its sub-commands for easier access. unload returns to the base console.
Example: Loading PADNS Context
SP# load padns
PADNS loaded
SP (PADNS)# query ns ig.com limit=1
{
"records": [
{
"answer": "dns1.p09.nsone.net",
"count": 5963,
"first_seen": "2020-12-26 00:41:26",
"last_seen": "2024-08-16 09:25:09",
"nshash": "981275157feda43a53ff6d166de985ff",
"query": "ig.com",
"ttl": 172800,
"type": "NS"
}
]
}
SP (PADNS)# answer ns dns1.p09.nsone.net limit=1
{
"records": [
{
"answer": "dns1.p09.nsone.net",
"count": 138,
"first_seen": "2024-01-27 21:23:33",
"last_seen": "2024-08-16 13:42:25",
"nshash": "9b484fe18c1a52f56775302e5be302f8",
"query": "tumblersforyou.com",
"ttl": 3600,
"type": "NS"
}
]
}
SP (PADNS)# unload padns
PADNS unloaded
SP#You can still run base commands (e.g., score) while in a loaded context.
Scripting
The CLI supports scripting for automation in projects.
run_pyscript Command
Execute a Python script that interacts with the CLI. Example script my_script.py):
# my_script.py
result = app('score ibm.com -t')
print(result.data)Run it with:
sp run_pyscript my_script.pyrun_script Command
Run a text file with CLI commands (one per line). Example file my_script.txt):
# my_script.txt
padns query mx ig.com limit=2
score ig.com -cExecute with:
sp run_script my_script.txtAlternatively, pipe input:
sp < my_script.txtBatch Execution Tips
Leverage shell scripting for efficient bulk operations. For example, enrich domains from a file:
cat to_enrich.txt | xargs sp bulk_enrichNote: Keep IOC types consistent in the file (e.g., all domains or all IPs) to avoid errors.
For Developers
Using the Library
Integrate the CLI as a Python library in your code.
Simple Usage
from sp.main import main as sp
sp(['enrich ig.com'])
sp(['padns query ns ig.com limit=2'])Advanced Usage with App Instance
from sp.main import App
from sp.common.utils import AppFileManager
app = App(application_manager=AppFileManager('my app'))
app.onecmd_plus_hooks('enrich ig.com')
print(app.last_result)
app.onecmd_plus_hooks('padns query ns ig.com limit=2')
print(app.last_result)Extend the Commands – Guidelines
Commands are defined in the sp/commands directory. The project uses the CMD2 library. To add a new command:
Create a new Python file in
sp/commands/(e.g.,my_new_command.py).Follow this template:
@with_default_category("My New Category")
class MyNewCommandSet(BaseCommandSet):
my_new_parser = BaseCommandSet._get_arg_parser()
my_new_parser.add_argument("-s", "--some_argument")
@with_argparser(my_new_parser)
def do_something(self, params: Statement):
with self.MyNewCommand(params, self) as my_new_command:
my_new_command.something()
class MyNewCommand(BaseCommand):
def __enter__(self):
# Pre-execution setup
super().__enter__()
return self
def something(self):
# Core logic
self._response = {"result": "your command result"}
def __exit__(self, exc_type, exc_val, exc_tb):
# Post-execution cleanup
super().__exit__(exc_type, exc_val, exc_tb)Import it in
sp/commands/__init__.py:
# After existing imports
from .my_new_command import *Add it to initial commands in
sp/settings.py:
def get_initial_commands():
from sp.commands import (
# Other imports
MyNewCommandSet
)
return {
# Other commands
MyNewCommandSet(),
}Test your command:
sp your_command --help