Skip to content

Commit

Permalink
Targets get_scope() will now pull from connected target (#9)
Browse files Browse the repository at this point in the history
* `targets.get_scope()` will now pull the scope of the connected target if no arguments provided
* Alphabetized defs for better organization
  • Loading branch information
bamhm182 authored Jul 13, 2022
1 parent 98d21d8 commit 95e72bf
Show file tree
Hide file tree
Showing 21 changed files with 1,641 additions and 1,584 deletions.
49 changes: 45 additions & 4 deletions checks.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
#!/bin/bash

flake8 src test live-tests
coverage run --source=src --omit=src/synack/db/alembic/env.py,src/synack/db/alembic/versions/*.py -m unittest discover test
coverage report | egrep -v "^[^T].*100%"
coverage html

diff_arrays() {
local -n _one=$1
local -n _two=$2
for ((i=0; i<${#_one[@]}; i++)); do
if [[ "${_one[$i]}" != "${_two[$i]}" ]]; then
echo -e "${_two[$i]}\t${_one[$i]}"
fi
done
}


for plugin in ./src/synack/plugins/*.py; do
p=$(basename ${plugin})
p=${p%.*}
defs=$(awk -F'[ (]*' '/def/ {print $3}' ${plugin} | egrep -v "__init|_fk_pragma")
defs=($(awk -F'[ (]*' '/ def / {print $3}' ${plugin} | egrep -v "__init__|__init_subclass__|_fk_pragma"))
readarray -t a_defs < <(printf '%s\n' "${defs[@]}" | sort)
if [[ "${defs[@]}" != "${a_defs[@]}" ]]; then
echo ${plugin} is not in alphabetical order
#echo -e "\tBad: ${defs[@]}"
#echo -e "\tGood: ${a_defs[@]}"
diff_arrays defs a_defs
fi
for def in ${defs}; do
grep "## ${p}.${def}" ./docs/src/usage/plugins/${p}.md > /dev/null 2>&1
if [[ $? != 0 ]]; then
Expand All @@ -19,3 +34,29 @@ for plugin in ./src/synack/plugins/*.py; do
fi
done
done

for test in ./test/test_*.py; do
defs=($(awk -F'[ (]*' '/ def / {print $3}' ${test} | egrep -v "__init__|setUp"))
readarray -t a_defs < <(printf '%s\n' "${defs[@]}" | sort)
if [[ "${defs[@]}" != "${a_defs[@]}" ]]; then
echo ${test} is not in alphabetical order
#echo -e "\tBad: ${defs[@]}"
#echo -e "\tGood: ${a_defs[@]}"
diff_arrays defs a_defs
fi
done

for doc in ./docs/src/usage/plugins/*.md; do
defs=($(awk -F'[ (]*' '/## / {print $2}' ${doc}))
readarray -t a_defs < <(printf '%s\n' "${defs[@]}" | sort)
if [[ "${defs[@]}" != "${a_defs[@]}" ]]; then
echo ${doc} is not in alphabetical order
#echo -e "\tBad: ${defs[@]}"
#echo -e "\tGood: ${a_defs[@]}"
diff_arrays defs a_defs
fi
done

coverage run --source=src --omit=src/synack/db/alembic/env.py,src/synack/db/alembic/versions/*.py -m unittest discover test
coverage report | egrep -v "^[^T].*100%"
coverage html
30 changes: 15 additions & 15 deletions docs/src/usage/plugins/alerts.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,6 @@ The Alerts Plugin is used to send alerts to various external services.

The functions within this plugin don't follow the standard naming convention.

## alerts.slack(message)

> This function makes a POST request to Slack in order to post a message.
> This function expects `h.db.slack_url` to be set.
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `message` | str | A message to send to Slack
>
>> Examples
>> ```python3
>> >>> h.db.synack_url = 'https://hooks.slack.com/services/x/y/z'
>> >>> h.alerts.slack('Something important happened!')
>> ```
## alerts.email(subject, message)

>> This function attempts to use SMTP to send an email.
Expand All @@ -40,3 +25,18 @@ The functions within this plugin don't follow the standard naming convention.
>> >>> h.db.smtp_email_from = '[email protected]'
>> >>> h.alerts.email('Look out!', 'Some other important thing happened!')
>> ```
## alerts.slack(message)
> This function makes a POST request to Slack in order to post a message.
> This function expects `h.db.slack_url` to be set.
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `message` | str | A message to send to Slack
>
>> Examples
>> ```python3
>> >>> h.db.synack_url = 'https://hooks.slack.com/services/x/y/z'
>> >>> h.alerts.slack('Something important happened!')
>> ```
36 changes: 18 additions & 18 deletions docs/src/usage/plugins/hydra.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
# Hydra

## hydra.get_hydra(page, max_page, update_db, **kwargs)

> Returns information from Synack Hydra Service
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `page` | int | Page of the Hydra Service to start on (Default: 1)
> | `max_page` | int | Highest page that should be queried (Default: 5)
> | `update_db` | bool | Store the results in the database
>
>> Examples
>> ```python3
>> >>> h.hydra.get_hydra(codename='SLEEPYPUPPY')
>> [{'host_plugins': {}, 'ip': '1.2.3.4', 'last_changed_dt': '2022-01-01T01:02:03Z', ... }, ... ]
>> >>> h.hydra.get_hydra(codename='SLEEPYPUPPY', page=3, max_page=5, update_db=False)
>> [{'host_plugins': {}, 'ip': '3.4.5.6', 'last_changed_dt': '2022-01-01T01:02:03Z', ... }, ... ]
>> ```
## hydra.build_db_input()

> Builds a list of ports ready to be ingested by the Database from Hydra output
Expand All @@ -36,3 +18,21 @@
>> ...
>> ]
>> ```
## hydra.get_hydra(page, max_page, update_db, **kwargs)
> Returns information from Synack Hydra Service
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `page` | int | Page of the Hydra Service to start on (Default: 1)
> | `max_page` | int | Highest page that should be queried (Default: 5)
> | `update_db` | bool | Store the results in the database
>
>> Examples
>> ```python3
>> >>> h.hydra.get_hydra(codename='SLEEPYPUPPY')
>> [{'host_plugins': {}, 'ip': '1.2.3.4', 'last_changed_dt': '2022-01-01T01:02:03Z', ... }, ... ]
>> >>> h.hydra.get_hydra(codename='SLEEPYPUPPY', page=3, max_page=5, update_db=False)
>> [{'host_plugins': {}, 'ip': '3.4.5.6', 'last_changed_dt': '2022-01-01T01:02:03Z', ... }, ... ]
>> ```
24 changes: 12 additions & 12 deletions docs/src/usage/plugins/scratchspace.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
# Scratchspace

## scratchspace.set_hosts_file(content, target=None, codename=None)
## scratchspace.build_filepath(filename, target=None, codename=None)

> This function will save a `hosts.txt` scope file within a `codename` folder in within the `self.db.scratchspace_dir` folder
> If `self.db.use_scratchspace` is `True`, this function is automatically run when you do `self.targets.get_scope()` or `self.targets.get_scope_host()`
> This function return the desired Scratchspace file name based on `db.scratchspace_dir` and a Target's Codename.
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `content` | str,list(str) | Either a preformatted string or (more likely) the return of `self.targets.get_scope_host()`
> | `filename` | str | Desired name of the destination file
> | `target` | db.models.Target | A Target Database Object
> | `codename` | str | Codename of a Target
>
>> Examples
>> ```python3
>> >>> scope = h.targets.get_scope_host(codename='ADAMANTARDVARK')
>> >>> h.scratchspace.set_hosts_file(scope, codename='ADAMANTARDVARK')
>> '/tmp/Scratchspace/ADAMANTARDVARK/hosts.txt'
>> >>> h.scratchspace.buildfilepath('test', codename='ADAMANTANT')
>> '/tmp/Scratchspace/ADAMANTANT/test.txt'
>> ```
## scratchspace.set_burp_file(content, target=None, codename=None)
Expand All @@ -36,18 +34,20 @@
>> '/tmp/Scratchspace/ADAMANTANT/burp.txt'
>> ```
## scratchspace.build_filepath(filename, target=None, codename=None)
## scratchspace.set_hosts_file(content, target=None, codename=None)
> This function return the desired Scratchspace file name based on `db.scratchspace_dir` and a Target's Codename.
> This function will save a `hosts.txt` scope file within a `codename` folder in within the `self.db.scratchspace_dir` folder
> If `self.db.use_scratchspace` is `True`, this function is automatically run when you do `self.targets.get_scope()` or `self.targets.get_scope_host()`
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `filename` | str | Desired name of the destination file
> | `content` | str,list(str) | Either a preformatted string or (more likely) the return of `self.targets.get_scope_host()`
> | `target` | db.models.Target | A Target Database Object
> | `codename` | str | Codename of a Target
>
>> Examples
>> ```python3
>> >>> h.scratchspace.buildfilepath('test', codename='ADAMANTANT')
>> '/tmp/Scratchspace/ADAMANTANT/test.txt'
>> >>> scope = h.targets.get_scope_host(codename='ADAMANTARDVARK')
>> >>> h.scratchspace.set_hosts_file(scope, codename='ADAMANTARDVARK')
>> '/tmp/Scratchspace/ADAMANTARDVARK/hosts.txt'
>> ```
86 changes: 44 additions & 42 deletions docs/src/usage/plugins/targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@
>> 'DAPPERDINGO'
>> ```
## targets.build_slug_from_codename(codename)
> Returns a Target's slug given its codename.
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `codename` | str | The codename of a Target
>
>> Examples
>> ```python3
>> >>> h.targets.build_slug_from_codename('DAPPERDINGO')
>> 'uwfpmfpgjlum'
>> ```
## targets.build_scope_host_db(slug, scope)
Expand Down Expand Up @@ -108,32 +95,30 @@
>> {'in': ['good.monkey.com'], 'out': ['bad.monkey.com']}
>> ```
## targets.get_assessments()
## targets.build_slug_from_codename(codename)
> Pull back a list of assessments and whether you have passed them.
> Returns a Target's slug given its codename.
>
> This function caches your status in the Database and will affect certain queries like `targets.get_unregistered()`, which will only pull back targets in categories you have passed.
> | Arguments | Type | Description
> | --- | --- | ---
> | `codename` | str | The codename of a Target
>
>> Examples
>> ```python3
>> >>> h.targets.get_assessments()
>> [{"id": 1, ...},...]
>> >>> h.targets.build_slug_from_codename('DAPPERDINGO')
>> 'uwfpmfpgjlum'
>> ```
## targets.get_credentials(**kwargs)
## targets.get_assessments()
> Pulls back the credentials for a Target
> Pull back a list of assessments and whether you have passed them.
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `kwargs` | kwargs | Some attribute that will be used to identify a Target
> This function caches your status in the Database and will affect certain queries like `targets.get_unregistered()`, which will only pull back targets in categories you have passed.
>
>> Examples
>> ```python3
>> >>> h.targets.get_credentials(slug='ljufpbgylu')
>> [{"credentials": [{...},...],...}]
>> >>> h.targets.get_credentials(codename='CHILLINCHILLA')
>> [{"credentials": [{...},...],...}]
>> >>> h.targets.get_assessments()
>> [{"id": 1, ...},...]
>> ```
## targets.get_connected()
Expand All @@ -146,22 +131,20 @@
>> {"slug": "ulmpupflgm", "codename": "GOOFYGOPHER", "status": "Connected"}
>> ```
## targets.get_scope_host(target, **kwargs)
## targets.get_credentials(**kwargs)
> Return CIDR IP Addresses in scope when given a Target or target identifiers
> Pulls back the credentials for a Target
>
> | Arguments | Type | Description
> | --- | --- | ---
> | `target` | db.models.Target | A single Target returned from the database
> | `kwargs` | kwargs | Information used to look up a Target in the database (ex: `codename`, `slug`, etc.)
> | `kwargs` | kwargs | Some attribute that will be used to identify a Target
>
>> Examples
>> ```python3
>> >>> tgt = h.db.find_targets(codename='SILLYFILLY')
>> >>> h.targets.get_scope_host(tgt)
>> ['1.1.1.1/32', '10.0.0.0/8', ...]
>> >>> h.targets.get_scope_host(slug='92wg38itur')
>> ['9,9,9,9/32', ...]
>> >>> h.targets.get_credentials(slug='ljufpbgylu')
>> [{"credentials": [{...},...],...}]
>> >>> h.targets.get_credentials(codename='CHILLINCHILLA')
>> [{"credentials": [{...},...],...}]
>> ```
## targets.get_registered_summary()
Expand All @@ -180,7 +163,8 @@
## targets.get_scope(**kwargs)
> Returns scope information for web or host targets when given target identifiers
> Returns scope information for web or host targets when given target identifiers.
> If no kwargs are provided, the scope of your currently connected target will be retrieved.
>
> | Arguments | Type | Description
> | --- | --- | ---
Expand All @@ -192,16 +176,22 @@
>> ['1.1.1.1/32', '10.0.0.0/8', ...]
>> ```
## targets.get_unregistered()
## targets.get_scope_host(target, **kwargs)
> Gets a list of unregistered Targets from the Synack API.
> Return CIDR IP Addresses in scope when given a Target or target identifiers
>
> Only Targets in Categories you have passed will be returned.
> | Arguments | Type | Description
> | --- | --- | ---
> | `target` | db.models.Target | A single Target returned from the database
> | `kwargs` | kwargs | Information used to look up a Target in the database (ex: `codename`, `slug`, etc.)
>
>> Examples
>> ```python3
>> >>> h.targets.get_unregistered()
>> [{"slug": "lfjpgmk",...},...]
>> >>> tgt = h.db.find_targets(codename='SILLYFILLY')
>> >>> h.targets.get_scope_host(tgt)
>> ['1.1.1.1/32', '10.0.0.0/8', ...]
>> >>> h.targets.get_scope_host(slug='92wg38itur')
>> ['9,9,9,9/32', ...]
>> ```
## targets.get_scope_web(target, **kwargs)
Expand All @@ -221,6 +211,18 @@
>> 'owners': [{'owner_uid': '97g8ehri', 'owner_type_id': 1, 'codename': 'slappyfrog'}, ...]
>> }, ...]
## targets.get_unregistered()
> Gets a list of unregistered Targets from the Synack API.
>
> Only Targets in Categories you have passed will be returned.
>
>> Examples
>> ```python3
>> >>> h.targets.get_unregistered()
>> [{"slug": "lfjpgmk",...},...]
>> ```
## targets.set_connected(target, **kwargs)
> Connect to a specified target
Expand Down
10 changes: 5 additions & 5 deletions src/synack/plugins/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ def __init__(self, *args, **kwargs):
plugin.lower(),
self.registry.get(plugin)(self.state))

def slack(self, message='This is a test'):
requests.post(self.db.slack_url,
data=json.dumps({'text': message}),
headers={'Content-Type': 'application/json'})

def email(self, subject='Test Alert', message='This is a test'):
message += f'\nTime: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}'
msg = email.message.EmailMessage()
Expand All @@ -40,3 +35,8 @@ def email(self, subject='Test Alert', message='This is a test'):

server.login(self.db.smtp_username, self.db.smtp_password)
server.send_message(msg)

def slack(self, message='This is a test'):
requests.post(self.db.slack_url,
data=json.dumps({'text': message}),
headers={'Content-Type': 'application/json'})
Loading

0 comments on commit 95e72bf

Please sign in to comment.