misp-modules 2.4.196__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- misp_modules/__init__.py +379 -0
- misp_modules/helpers/__init__.py +1 -0
- misp_modules/helpers/cache.py +84 -0
- misp_modules/lib/__init__.py +4 -0
- misp_modules/lib/_vmray/__init__.py +0 -0
- misp_modules/lib/_vmray/parser.py +1417 -0
- misp_modules/lib/_vmray/rest_api.py +148 -0
- misp_modules/lib/cof2misp/LICENSE-2.0.txt +202 -0
- misp_modules/lib/cof2misp/__init__.py +0 -0
- misp_modules/lib/cof2misp/cof.py +165 -0
- misp_modules/lib/joe_mapping.py +114 -0
- misp_modules/lib/joe_parser.py +573 -0
- misp_modules/lib/lastline_api.py +841 -0
- misp_modules/lib/qintel_helper.py +263 -0
- misp_modules/lib/stix2misp.py +2080 -0
- misp_modules/lib/stix2misp_mapping.py +460 -0
- misp_modules/lib/synonymsToTagNames.json +1 -0
- misp_modules/lib/vt_graph_parser/__init__.py +8 -0
- misp_modules/lib/vt_graph_parser/errors.py +20 -0
- misp_modules/lib/vt_graph_parser/helpers/__init__.py +7 -0
- misp_modules/lib/vt_graph_parser/helpers/parsers.py +88 -0
- misp_modules/lib/vt_graph_parser/helpers/rules.py +304 -0
- misp_modules/lib/vt_graph_parser/helpers/wrappers.py +58 -0
- misp_modules/lib/vt_graph_parser/importers/__init__.py +7 -0
- misp_modules/lib/vt_graph_parser/importers/base.py +98 -0
- misp_modules/lib/vt_graph_parser/importers/pymisp_response.py +73 -0
- misp_modules/modules/__init__.py +4 -0
- misp_modules/modules/action_mod/__init__.py +1 -0
- misp_modules/modules/action_mod/_utils/__init__.py +1 -0
- misp_modules/modules/action_mod/_utils/utils.py +70 -0
- misp_modules/modules/action_mod/mattermost.py +113 -0
- misp_modules/modules/action_mod/slack.py +96 -0
- misp_modules/modules/action_mod/testaction.py +68 -0
- misp_modules/modules/expansion/__init__.py +36 -0
- misp_modules/modules/expansion/_dnsdb_query/COPYRIGHT +27 -0
- misp_modules/modules/expansion/_dnsdb_query/LICENSE +202 -0
- misp_modules/modules/expansion/_dnsdb_query/README.md +162 -0
- misp_modules/modules/expansion/_dnsdb_query/__init__.py +0 -0
- misp_modules/modules/expansion/_dnsdb_query/dnsdb_query.py +327 -0
- misp_modules/modules/expansion/_ransomcoindb/__init__.py +0 -0
- misp_modules/modules/expansion/_ransomcoindb/ransomcoindb.py +96 -0
- misp_modules/modules/expansion/_vulnerability_parser/__init__.py +0 -0
- misp_modules/modules/expansion/_vulnerability_parser/vulnerability_parser.py +118 -0
- misp_modules/modules/expansion/abuseipdb.py +146 -0
- misp_modules/modules/expansion/apiosintds.py +365 -0
- misp_modules/modules/expansion/apivoid.py +133 -0
- misp_modules/modules/expansion/assemblyline_query.py +179 -0
- misp_modules/modules/expansion/assemblyline_submit.py +100 -0
- misp_modules/modules/expansion/backscatter_io.py +84 -0
- misp_modules/modules/expansion/btc_scam_check.py +54 -0
- misp_modules/modules/expansion/btc_steroids.py +238 -0
- misp_modules/modules/expansion/censys_enrich.py +287 -0
- misp_modules/modules/expansion/circl_passivedns.py +85 -0
- misp_modules/modules/expansion/circl_passivessl.py +113 -0
- misp_modules/modules/expansion/clamav.py +129 -0
- misp_modules/modules/expansion/cluster25_expand.py +239 -0
- misp_modules/modules/expansion/countrycode.py +69 -0
- misp_modules/modules/expansion/cpe.py +140 -0
- misp_modules/modules/expansion/crowdsec.py +235 -0
- misp_modules/modules/expansion/crowdstrike_falcon.py +148 -0
- misp_modules/modules/expansion/cuckoo_submit.py +161 -0
- misp_modules/modules/expansion/cve.py +57 -0
- misp_modules/modules/expansion/cve_advanced.py +185 -0
- misp_modules/modules/expansion/cytomic_orion.py +196 -0
- misp_modules/modules/expansion/dbl_spamhaus.py +78 -0
- misp_modules/modules/expansion/dns.py +71 -0
- misp_modules/modules/expansion/docx_enrich.py +71 -0
- misp_modules/modules/expansion/domaintools.py +290 -0
- misp_modules/modules/expansion/eql.py +91 -0
- misp_modules/modules/expansion/eupi.py +86 -0
- misp_modules/modules/expansion/extract_url_components.py +83 -0
- misp_modules/modules/expansion/farsight_passivedns.py +243 -0
- misp_modules/modules/expansion/geoip_asn.py +75 -0
- misp_modules/modules/expansion/geoip_city.py +75 -0
- misp_modules/modules/expansion/geoip_country.py +73 -0
- misp_modules/modules/expansion/google_safe_browsing.py +86 -0
- misp_modules/modules/expansion/google_search.py +57 -0
- misp_modules/modules/expansion/google_threat_intelligence.py +453 -0
- misp_modules/modules/expansion/greynoise.py +346 -0
- misp_modules/modules/expansion/hashdd.py +53 -0
- misp_modules/modules/expansion/hashlookup.py +118 -0
- misp_modules/modules/expansion/hibp.py +62 -0
- misp_modules/modules/expansion/html_to_markdown.py +63 -0
- misp_modules/modules/expansion/hyasinsight.py +881 -0
- misp_modules/modules/expansion/intel471.py +73 -0
- misp_modules/modules/expansion/intelmq_eventdb.py.experimental +67 -0
- misp_modules/modules/expansion/ip2locationio.py +90 -0
- misp_modules/modules/expansion/ipasn.py +70 -0
- misp_modules/modules/expansion/ipinfo.py +112 -0
- misp_modules/modules/expansion/ipqs_fraud_and_risk_scoring.py +633 -0
- misp_modules/modules/expansion/iprep.py +98 -0
- misp_modules/modules/expansion/jinja_template_rendering.py +54 -0
- misp_modules/modules/expansion/joesandbox_query.py +91 -0
- misp_modules/modules/expansion/joesandbox_submit.py +147 -0
- misp_modules/modules/expansion/lastline_query.py +148 -0
- misp_modules/modules/expansion/lastline_submit.py +180 -0
- misp_modules/modules/expansion/macaddress_io.py +130 -0
- misp_modules/modules/expansion/macvendors.py +55 -0
- misp_modules/modules/expansion/malshare_upload.py +107 -0
- misp_modules/modules/expansion/malwarebazaar.py +67 -0
- misp_modules/modules/expansion/mcafee_insights_enrich.py +249 -0
- misp_modules/modules/expansion/mmdb_lookup.py +138 -0
- misp_modules/modules/expansion/module.py.skeleton +44 -0
- misp_modules/modules/expansion/mwdb.py +152 -0
- misp_modules/modules/expansion/ocr_enrich.py +74 -0
- misp_modules/modules/expansion/ods_enrich.py +71 -0
- misp_modules/modules/expansion/odt_enrich.py +61 -0
- misp_modules/modules/expansion/onyphe.py +243 -0
- misp_modules/modules/expansion/onyphe_full.py +387 -0
- misp_modules/modules/expansion/otx.py +167 -0
- misp_modules/modules/expansion/passive_ssh.py +150 -0
- misp_modules/modules/expansion/passivetotal.py +358 -0
- misp_modules/modules/expansion/pdf_enrich.py +58 -0
- misp_modules/modules/expansion/pptx_enrich.py +65 -0
- misp_modules/modules/expansion/qintel_qsentry.py +229 -0
- misp_modules/modules/expansion/qrcode.py +99 -0
- misp_modules/modules/expansion/ransomcoindb.py +82 -0
- misp_modules/modules/expansion/rbl.py +126 -0
- misp_modules/modules/expansion/recordedfuture.py +544 -0
- misp_modules/modules/expansion/reversedns.py +77 -0
- misp_modules/modules/expansion/securitytrails.py +571 -0
- misp_modules/modules/expansion/shodan.py +244 -0
- misp_modules/modules/expansion/sigma_queries.py +61 -0
- misp_modules/modules/expansion/sigma_syntax_validator.py +49 -0
- misp_modules/modules/expansion/sigmf_expand.py +303 -0
- misp_modules/modules/expansion/socialscan.py +108 -0
- misp_modules/modules/expansion/sophoslabs_intelix.py +146 -0
- misp_modules/modules/expansion/sourcecache.py +57 -0
- misp_modules/modules/expansion/stairwell.py +156 -0
- misp_modules/modules/expansion/stix2_pattern_syntax_validator.py +56 -0
- misp_modules/modules/expansion/threatcrowd.py +170 -0
- misp_modules/modules/expansion/threatfox.py +75 -0
- misp_modules/modules/expansion/threatminer.py +152 -0
- misp_modules/modules/expansion/triage_submit.py +119 -0
- misp_modules/modules/expansion/trustar_enrich.py +235 -0
- misp_modules/modules/expansion/urlhaus.py +164 -0
- misp_modules/modules/expansion/urlscan.py +269 -0
- misp_modules/modules/expansion/variotdbs.py +133 -0
- misp_modules/modules/expansion/virustotal.py +311 -0
- misp_modules/modules/expansion/virustotal_public.py +272 -0
- misp_modules/modules/expansion/virustotal_upload.py +91 -0
- misp_modules/modules/expansion/vmray_submit.py +161 -0
- misp_modules/modules/expansion/vmware_nsx.py +628 -0
- misp_modules/modules/expansion/vulndb.py +292 -0
- misp_modules/modules/expansion/vulnerability_lookup.py +324 -0
- misp_modules/modules/expansion/vulners.py +81 -0
- misp_modules/modules/expansion/vysion.py +221 -0
- misp_modules/modules/expansion/whois.py +72 -0
- misp_modules/modules/expansion/whoisfreaks.py +232 -0
- misp_modules/modules/expansion/wiki.py +58 -0
- misp_modules/modules/expansion/xforceexchange.py +189 -0
- misp_modules/modules/expansion/xlsx_enrich.py +63 -0
- misp_modules/modules/expansion/yara_query.py +70 -0
- misp_modules/modules/expansion/yara_syntax_validator.py +49 -0
- misp_modules/modules/expansion/yeti.py +196 -0
- misp_modules/modules/export_mod/__init__.py +3 -0
- misp_modules/modules/export_mod/cef_export.py +93 -0
- misp_modules/modules/export_mod/cisco_firesight_manager_ACL_rule_export.py +150 -0
- misp_modules/modules/export_mod/defender_endpoint_export.py +141 -0
- misp_modules/modules/export_mod/goamlexport.py +255 -0
- misp_modules/modules/export_mod/liteexport.py +97 -0
- misp_modules/modules/export_mod/mass_eql_export.py +106 -0
- misp_modules/modules/export_mod/nexthinkexport.py +131 -0
- misp_modules/modules/export_mod/osqueryexport.py +125 -0
- misp_modules/modules/export_mod/pdfexport.py +107 -0
- misp_modules/modules/export_mod/testexport.py +73 -0
- misp_modules/modules/export_mod/threatStream_misp_export.py +114 -0
- misp_modules/modules/export_mod/threat_connect_export.py +125 -0
- misp_modules/modules/export_mod/virustotal_collections.py +141 -0
- misp_modules/modules/export_mod/vt_graph.py +120 -0
- misp_modules/modules/export_mod/yara_export.py +290 -0
- misp_modules/modules/import_mod/__init__.py +22 -0
- misp_modules/modules/import_mod/cof2misp.py +264 -0
- misp_modules/modules/import_mod/csvimport.py +319 -0
- misp_modules/modules/import_mod/cuckooimport.py +749 -0
- misp_modules/modules/import_mod/email_import.py +294 -0
- misp_modules/modules/import_mod/goamlimport.py +188 -0
- misp_modules/modules/import_mod/import_blueprint.py +93 -0
- misp_modules/modules/import_mod/joe_import.py +74 -0
- misp_modules/modules/import_mod/lastline_import.py +160 -0
- misp_modules/modules/import_mod/mispjson.py +73 -0
- misp_modules/modules/import_mod/ocr.py +122 -0
- misp_modules/modules/import_mod/openiocimport.py +99 -0
- misp_modules/modules/import_mod/taxii21.py +383 -0
- misp_modules/modules/import_mod/testimport.py +73 -0
- misp_modules/modules/import_mod/threatanalyzer_import.py +552 -0
- misp_modules/modules/import_mod/url_import.py +97 -0
- misp_modules/modules/import_mod/vmray_import.py +96 -0
- misp_modules/modules/import_mod/vmray_summary_json_import.py +87 -0
- misp_modules-2.4.196.dist-info/LICENSE +661 -0
- misp_modules-2.4.196.dist-info/METADATA +281 -0
- misp_modules-2.4.196.dist-info/RECORD +194 -0
- misp_modules-2.4.196.dist-info/WHEEL +4 -0
- misp_modules-2.4.196.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
dnsdb-query
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
These clients are reference implementations of the [DNSDB HTTP API](https://api.dnsdb.info/). Output is
|
|
5
|
+
compliant with the [Passive DNS Common Output Format](http://tools.ietf.org/html/draft-dulaunoy-kaplan-passive-dns-cof-01).
|
|
6
|
+
|
|
7
|
+
Please see https://www.dnsdb.info/ for more information.
|
|
8
|
+
|
|
9
|
+
Requirements
|
|
10
|
+
------------
|
|
11
|
+
* Linux, BSD, OS X
|
|
12
|
+
* Curl
|
|
13
|
+
* Python 2.7.x
|
|
14
|
+
* Farsight DNSDB API key
|
|
15
|
+
|
|
16
|
+
Installation
|
|
17
|
+
------------
|
|
18
|
+
1. Create a directory
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
mkdir ~/dnsdb
|
|
22
|
+
```
|
|
23
|
+
1. Download the software
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
curl https://codeload.github.com/dnsdb/dnsdb-query/tar.gz/debian/0.2-1 -o ~/dnsdb/0.2-1.tar.gz
|
|
27
|
+
```
|
|
28
|
+
1. Extract the software
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
tar xzvf ~/dnsdb/0.2-1.tar.gz -C ~/dnsdb/ --strip-components=1
|
|
32
|
+
```
|
|
33
|
+
1. Create a API key file
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
nano ~/.dnsdb-query.conf
|
|
37
|
+
```
|
|
38
|
+
1. Cut and paste the following and replace '\<apikey\>' with your API Key
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
APIKEY="<apikey>"
|
|
42
|
+
```
|
|
43
|
+
1. Test the Python client
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
$ python dnsdb/dnsdb_query.py -i 104.244.13.104
|
|
47
|
+
```
|
|
48
|
+
```
|
|
49
|
+
...
|
|
50
|
+
www.farsightsecurity.com. IN A 104.244.13.104
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
dnsdb_query.py
|
|
54
|
+
--------------
|
|
55
|
+
|
|
56
|
+
dnsdb_query.py is a Python client for the DNSDB HTTP API. It is similar
|
|
57
|
+
to the dnsdb-query shell script but supports some additional features
|
|
58
|
+
like sorting and setting the result limit parameter. It is also embeddable
|
|
59
|
+
as a Python module.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Usage: dnsdb_query.py [options]
|
|
63
|
+
|
|
64
|
+
Options:
|
|
65
|
+
-h, --help show this help message and exit
|
|
66
|
+
-c CONFIG, --config=CONFIG
|
|
67
|
+
config file
|
|
68
|
+
-r RRSET, --rrset=RRSET
|
|
69
|
+
rrset <ONAME>[/<RRTYPE>[/BAILIWICK]]
|
|
70
|
+
-n RDATA_NAME, --rdataname=RDATA_NAME
|
|
71
|
+
rdata name <NAME>[/<RRTYPE>]
|
|
72
|
+
-i RDATA_IP, --rdataip=RDATA_IP
|
|
73
|
+
rdata ip <IPADDRESS|IPRANGE|IPNETWORK>
|
|
74
|
+
-s SORT, --sort=SORT sort key
|
|
75
|
+
-R, --reverse reverse sort
|
|
76
|
+
-j, --json output in JSON format
|
|
77
|
+
-l LIMIT, --limit=LIMIT
|
|
78
|
+
limit number of results
|
|
79
|
+
--before=BEFORE only output results seen before this time
|
|
80
|
+
--after=AFTER only output results seen after this time
|
|
81
|
+
|
|
82
|
+
Time formats are: "%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%d" (UNIX timestamp),
|
|
83
|
+
"-%d" (Relative time in seconds), BIND format relative timestamp (e.g. 1w1h,
|
|
84
|
+
(w)eek, (d)ay, (h)our, (m)inute, (s)econd)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Or, from Python:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
from dnsdb_query import DnsdbClient
|
|
91
|
+
|
|
92
|
+
server='https://api.dnsdb.info'
|
|
93
|
+
apikey='d41d8cd98f00b204e9800998ecf8427e'
|
|
94
|
+
|
|
95
|
+
client = DnsdbClient(server,apikey)
|
|
96
|
+
for rrset in client.query_rrset('www.dnsdb.info'):
|
|
97
|
+
# rrset is a decoded JSON blob
|
|
98
|
+
print repr(rrset)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Other configuration options that may be set:
|
|
102
|
+
|
|
103
|
+
`DNSDB_SERVER`
|
|
104
|
+
The base URL of the DNSDB HTTP API, minus the /lookup component. Defaults to
|
|
105
|
+
`https://api.dnsdb.info.`
|
|
106
|
+
|
|
107
|
+
`HTTP_PROXY`
|
|
108
|
+
The URL of the HTTP proxy that you wish to use.
|
|
109
|
+
|
|
110
|
+
`HTTPS_PROXY`
|
|
111
|
+
The URL of the HTTPS proxy that you wish to use.
|
|
112
|
+
|
|
113
|
+
dnsdb-query
|
|
114
|
+
-----------
|
|
115
|
+
|
|
116
|
+
dnsdb-query is a simple curl-based wrapper for the DNSDB HTTP API.
|
|
117
|
+
|
|
118
|
+
The script sources the config file `/etc/dnsdb-query.conf` as a shell fragment.
|
|
119
|
+
If the config file is not present in `/etc`, the file `$HOME/.dnsdb-query.conf`
|
|
120
|
+
is sourced instead.
|
|
121
|
+
|
|
122
|
+
The config file MUST set the value of the APIKEY shell variable to the API
|
|
123
|
+
key provided to you by Farsight Security.
|
|
124
|
+
|
|
125
|
+
For example, if your API key is d41d8cd98f00b204e9800998ecf8427e, place the
|
|
126
|
+
following line in `/etc/dnsdb-query.conf` or `$HOME/.dnsdb-query.conf`:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
APIKEY="d41d8cd98f00b204e9800998ecf8427e"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Other shell variables that may be set via the config file or command line
|
|
133
|
+
are:
|
|
134
|
+
|
|
135
|
+
`DNSDB_SERVER`
|
|
136
|
+
The base URL of the DNSDB HTTP API, minus the /lookup component. Defaults to
|
|
137
|
+
`https://api.dnsdb.info.`
|
|
138
|
+
|
|
139
|
+
`DNSDB_FORMAT`
|
|
140
|
+
The result format to use, either text or json. Defaults to text.
|
|
141
|
+
|
|
142
|
+
`HTTP_PROXY`
|
|
143
|
+
The URL of the HTTP proxy that you wish to use.
|
|
144
|
+
|
|
145
|
+
`HTTPS_PROXY`
|
|
146
|
+
The URL of the HTTPS proxy that you wish to use.
|
|
147
|
+
|
|
148
|
+
dnsdb-query supports the following usages:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Usage: dnsdb-query rrset <ONAME>[/<RRTYPE>[/<BAILIWICK>]]
|
|
152
|
+
Usage: dnsdb-query rdata ip <IPADDRESS>
|
|
153
|
+
Usage: dnsdb-query rdata name <NAME>[/<RRTYPE>]
|
|
154
|
+
Usage: dnsdb-query rdata raw <HEX>[/<RRTYPE>]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
If your rrname, bailiwick or rdata contains the `/` character you
|
|
158
|
+
will need to escape it to `%2F` on the command line. eg:
|
|
159
|
+
|
|
160
|
+
`./dnsdb_query -r 1.0%2F1.0.168.192.in-addr.arpa`
|
|
161
|
+
|
|
162
|
+
retrieves the rrsets for `1.0/1.0.168.192.in-addr.arpa`.
|
|
File without changes
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Note: This file is NOT the official one from dnsdb, as it has a python3 cherry-picked pull-request applied for python3 compatibility
|
|
4
|
+
# See https://github.com/dnsdb/dnsdb-query/pull/30
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2013 by Farsight Security, Inc.
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
# you may not use this file except in compliance with the License.
|
|
10
|
+
# You may obtain a copy of the License at
|
|
11
|
+
#
|
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
#
|
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
# See the License for the specific language governing permissions and
|
|
18
|
+
# limitations under the License.
|
|
19
|
+
from __future__ import print_function
|
|
20
|
+
|
|
21
|
+
import calendar
|
|
22
|
+
import errno
|
|
23
|
+
import locale
|
|
24
|
+
import optparse
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
import sys
|
|
28
|
+
import time
|
|
29
|
+
import json
|
|
30
|
+
from io import StringIO
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
from urllib2 import build_opener, Request, ProxyHandler, HTTPError, URLError
|
|
34
|
+
from urllib import quote as urllib_quote, urlencode
|
|
35
|
+
except ImportError:
|
|
36
|
+
from urllib.request import build_opener, Request, ProxyHandler, HTTPError, URLError
|
|
37
|
+
from urllib.parse import quote as urllib_quote, urlencode
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
DEFAULT_CONFIG_FILES = filter(os.path.isfile, ('/etc/dnsdb-query.conf', os.path.expanduser('~/.dnsdb-query.conf')))
|
|
41
|
+
DEFAULT_DNSDB_SERVER = 'https://api.dnsdb.info'
|
|
42
|
+
DEFAULT_HTTP_PROXY = ''
|
|
43
|
+
DEFAULT_HTTPS_PROXY = ''
|
|
44
|
+
|
|
45
|
+
cfg = None
|
|
46
|
+
options = None
|
|
47
|
+
|
|
48
|
+
locale.setlocale(locale.LC_ALL, '')
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class QueryError(Exception):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class DnsdbClient(object):
|
|
56
|
+
def __init__(self, server, apikey, limit=None, http_proxy=None, https_proxy=None):
|
|
57
|
+
self.server = server
|
|
58
|
+
self.apikey = apikey
|
|
59
|
+
self.limit = limit
|
|
60
|
+
self.http_proxy = http_proxy
|
|
61
|
+
self.https_proxy = https_proxy
|
|
62
|
+
|
|
63
|
+
def query_rrset(self, oname, rrtype=None, bailiwick=None, before=None, after=None):
|
|
64
|
+
if bailiwick:
|
|
65
|
+
if not rrtype:
|
|
66
|
+
rrtype = 'ANY'
|
|
67
|
+
path = 'rrset/name/%s/%s/%s' % (quote(oname), rrtype, quote(bailiwick))
|
|
68
|
+
elif rrtype:
|
|
69
|
+
path = 'rrset/name/%s/%s' % (quote(oname), rrtype)
|
|
70
|
+
else:
|
|
71
|
+
path = 'rrset/name/%s' % quote(oname)
|
|
72
|
+
return self._query(path, before, after)
|
|
73
|
+
|
|
74
|
+
def query_rdata_name(self, rdata_name, rrtype=None, before=None, after=None):
|
|
75
|
+
if rrtype:
|
|
76
|
+
path = 'rdata/name/%s/%s' % (quote(rdata_name), rrtype)
|
|
77
|
+
else:
|
|
78
|
+
path = 'rdata/name/%s' % quote(rdata_name)
|
|
79
|
+
return self._query(path, before, after)
|
|
80
|
+
|
|
81
|
+
def query_rdata_ip(self, rdata_ip, before=None, after=None):
|
|
82
|
+
path = 'rdata/ip/%s' % rdata_ip.replace('/', ',')
|
|
83
|
+
return self._query(path, before, after)
|
|
84
|
+
|
|
85
|
+
def _query(self, path, before=None, after=None):
|
|
86
|
+
url = '%s/lookup/%s' % (self.server, path)
|
|
87
|
+
|
|
88
|
+
params = {}
|
|
89
|
+
if self.limit:
|
|
90
|
+
params['limit'] = self.limit
|
|
91
|
+
if before and after:
|
|
92
|
+
params['time_first_after'] = after
|
|
93
|
+
params['time_last_before'] = before
|
|
94
|
+
else:
|
|
95
|
+
if before:
|
|
96
|
+
params['time_first_before'] = before
|
|
97
|
+
if after:
|
|
98
|
+
params['time_last_after'] = after
|
|
99
|
+
if params:
|
|
100
|
+
url += '?{0}'.format(urlencode(params))
|
|
101
|
+
|
|
102
|
+
req = Request(url)
|
|
103
|
+
req.add_header('Accept', 'application/json')
|
|
104
|
+
req.add_header('X-Api-Key', self.apikey)
|
|
105
|
+
|
|
106
|
+
proxy_args = {}
|
|
107
|
+
if self.http_proxy:
|
|
108
|
+
proxy_args['http'] = self.http_proxy
|
|
109
|
+
if self.https_proxy:
|
|
110
|
+
proxy_args['https'] = self.https_proxy
|
|
111
|
+
proxy_handler = ProxyHandler(proxy_args)
|
|
112
|
+
opener = build_opener(proxy_handler)
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
http = opener.open(req)
|
|
116
|
+
while True:
|
|
117
|
+
line = http.readline()
|
|
118
|
+
if not line:
|
|
119
|
+
break
|
|
120
|
+
yield json.loads(line.decode('ascii'))
|
|
121
|
+
except (HTTPError, URLError) as e:
|
|
122
|
+
try:
|
|
123
|
+
raise QueryError(str(e), sys.exc_traceback)
|
|
124
|
+
except AttributeError:
|
|
125
|
+
raise QueryError(str(e), sys.exc_info)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def quote(path):
|
|
129
|
+
return urllib_quote(path, safe='')
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def sec_to_text(ts):
|
|
133
|
+
return time.strftime('%Y-%m-%d %H:%M:%S -0000', time.gmtime(ts))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def rrset_to_text(m):
|
|
137
|
+
s = StringIO()
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
if 'bailiwick' in m:
|
|
141
|
+
s.write(';; bailiwick: %s\n' % m['bailiwick'])
|
|
142
|
+
|
|
143
|
+
if 'count' in m:
|
|
144
|
+
s.write(';; count: %s\n' % locale.format('%d', m['count'], True))
|
|
145
|
+
|
|
146
|
+
if 'time_first' in m:
|
|
147
|
+
s.write(';; first seen: %s\n' % sec_to_text(m['time_first']))
|
|
148
|
+
if 'time_last' in m:
|
|
149
|
+
s.write(';; last seen: %s\n' % sec_to_text(m['time_last']))
|
|
150
|
+
|
|
151
|
+
if 'zone_time_first' in m:
|
|
152
|
+
s.write(';; first seen in zone file: %s\n' % sec_to_text(m['zone_time_first']))
|
|
153
|
+
if 'zone_time_last' in m:
|
|
154
|
+
s.write(';; last seen in zone file: %s\n' % sec_to_text(m['zone_time_last']))
|
|
155
|
+
|
|
156
|
+
if 'rdata' in m:
|
|
157
|
+
for rdata in m['rdata']:
|
|
158
|
+
s.write('%s IN %s %s\n' % (m['rrname'], m['rrtype'], rdata))
|
|
159
|
+
|
|
160
|
+
s.seek(0)
|
|
161
|
+
return s.read()
|
|
162
|
+
finally:
|
|
163
|
+
s.close()
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def rdata_to_text(m):
|
|
167
|
+
return '%s IN %s %s' % (m['rrname'], m['rrtype'], m['rdata'])
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def parse_config(cfg_files):
|
|
171
|
+
config = {}
|
|
172
|
+
|
|
173
|
+
if not cfg_files:
|
|
174
|
+
raise IOError(errno.ENOENT, 'dnsdb_query: No config files found')
|
|
175
|
+
|
|
176
|
+
for fname in cfg_files:
|
|
177
|
+
for line in open(fname):
|
|
178
|
+
key, eq, val = line.strip().partition('=')
|
|
179
|
+
val = val.strip('"')
|
|
180
|
+
config[key] = val
|
|
181
|
+
|
|
182
|
+
return config
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def time_parse(s):
|
|
186
|
+
try:
|
|
187
|
+
epoch = int(s)
|
|
188
|
+
return epoch
|
|
189
|
+
except ValueError:
|
|
190
|
+
pass
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
epoch = int(calendar.timegm(time.strptime(s, '%Y-%m-%d')))
|
|
194
|
+
return epoch
|
|
195
|
+
except ValueError:
|
|
196
|
+
pass
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
epoch = int(calendar.timegm(time.strptime(s, '%Y-%m-%d %H:%M:%S')))
|
|
200
|
+
return epoch
|
|
201
|
+
except ValueError:
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
m = re.match(r'^(?=\d)(?:(\d+)w)?(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s?)?$', s, re.I)
|
|
205
|
+
if m:
|
|
206
|
+
return -1 * (int(m.group(1) or 0) * 604800
|
|
207
|
+
+ int(m.group(2) or 0) * 86400
|
|
208
|
+
+ int(m.group(3) or 0) * 3600
|
|
209
|
+
+ int(m.group(4) or 0) * 60
|
|
210
|
+
+ int(m.group(5) or 0))
|
|
211
|
+
|
|
212
|
+
raise ValueError('Invalid time: "%s"' % s)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def epipe_wrapper(func):
|
|
216
|
+
def f(*args, **kwargs):
|
|
217
|
+
try:
|
|
218
|
+
return func(*args, **kwargs)
|
|
219
|
+
except IOError as e:
|
|
220
|
+
if e.errno == errno.EPIPE:
|
|
221
|
+
sys.exit(e.errno)
|
|
222
|
+
raise
|
|
223
|
+
return f
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@epipe_wrapper
|
|
227
|
+
def main():
|
|
228
|
+
global cfg
|
|
229
|
+
global options
|
|
230
|
+
|
|
231
|
+
parser = optparse.OptionParser(epilog='Time formats are: "%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%d" (UNIX timestamp), "-%d" (Relative time in seconds), BIND format (e.g. 1w1h, (w)eek, (d)ay, (h)our, (m)inute, (s)econd)')
|
|
232
|
+
parser.add_option('-c', '--config', dest='config', help='config file', action='append')
|
|
233
|
+
parser.add_option('-r', '--rrset', dest='rrset', type='string', help='rrset <ONAME>[/<RRTYPE>[/BAILIWICK]]')
|
|
234
|
+
parser.add_option('-n', '--rdataname', dest='rdata_name', type='string', help='rdata name <NAME>[/<RRTYPE>]')
|
|
235
|
+
parser.add_option('-i', '--rdataip', dest='rdata_ip', type='string', help='rdata ip <IPADDRESS|IPRANGE|IPNETWORK>')
|
|
236
|
+
parser.add_option('-t', '--rrtype', dest='rrtype', type='string', help='rrset or rdata rrtype')
|
|
237
|
+
parser.add_option('-b', '--bailiwick', dest='bailiwick', type='string', help='rrset bailiwick')
|
|
238
|
+
parser.add_option('-s', '--sort', dest='sort', type='string', help='sort key')
|
|
239
|
+
parser.add_option('-R', '--reverse', dest='reverse', action='store_true', default=False, help='reverse sort')
|
|
240
|
+
parser.add_option('-j', '--json', dest='json', action='store_true', default=False, help='output in JSON format')
|
|
241
|
+
parser.add_option('-l', '--limit', dest='limit', type='int', default=0, help='limit number of results')
|
|
242
|
+
|
|
243
|
+
parser.add_option('', '--before', dest='before', type='string', help='only output results seen before this time')
|
|
244
|
+
parser.add_option('', '--after', dest='after', type='string', help='only output results seen after this time')
|
|
245
|
+
|
|
246
|
+
options, args = parser.parse_args()
|
|
247
|
+
if args:
|
|
248
|
+
parser.print_help()
|
|
249
|
+
sys.exit(1)
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
if options.before:
|
|
253
|
+
options.before = time_parse(options.before)
|
|
254
|
+
except ValueError:
|
|
255
|
+
print('Could not parse before: {}'.format(options.before))
|
|
256
|
+
|
|
257
|
+
try:
|
|
258
|
+
if options.after:
|
|
259
|
+
options.after = time_parse(options.after)
|
|
260
|
+
except ValueError:
|
|
261
|
+
print('Could not parse after: {}'.format(options.after))
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
cfg = parse_config(options.config or DEFAULT_CONFIG_FILES)
|
|
265
|
+
except IOError as e:
|
|
266
|
+
print(str(e), file=sys.stderr)
|
|
267
|
+
sys.exit(1)
|
|
268
|
+
|
|
269
|
+
if 'DNSDB_SERVER' not in cfg:
|
|
270
|
+
cfg['DNSDB_SERVER'] = DEFAULT_DNSDB_SERVER
|
|
271
|
+
if 'HTTP_PROXY' not in cfg:
|
|
272
|
+
cfg['HTTP_PROXY'] = DEFAULT_HTTP_PROXY
|
|
273
|
+
if 'HTTPS_PROXY' not in cfg:
|
|
274
|
+
cfg['HTTPS_PROXY'] = DEFAULT_HTTPS_PROXY
|
|
275
|
+
if 'APIKEY' not in cfg:
|
|
276
|
+
sys.stderr.write('dnsdb_query: APIKEY not defined in config file\n')
|
|
277
|
+
sys.exit(1)
|
|
278
|
+
|
|
279
|
+
client = DnsdbClient(cfg['DNSDB_SERVER'], cfg['APIKEY'],
|
|
280
|
+
limit=options.limit,
|
|
281
|
+
http_proxy=cfg['HTTP_PROXY'],
|
|
282
|
+
https_proxy=cfg['HTTPS_PROXY'])
|
|
283
|
+
if options.rrset:
|
|
284
|
+
if options.rrtype or options.bailiwick:
|
|
285
|
+
qargs = (options.rrset, options.rrtype, options.bailiwick)
|
|
286
|
+
else:
|
|
287
|
+
qargs = (options.rrset.split('/', 2))
|
|
288
|
+
|
|
289
|
+
results = client.query_rrset(*qargs, before=options.before, after=options.after)
|
|
290
|
+
fmt_func = rrset_to_text
|
|
291
|
+
elif options.rdata_name:
|
|
292
|
+
if options.rrtype:
|
|
293
|
+
qargs = (options.rdata_name, options.rrtype)
|
|
294
|
+
else:
|
|
295
|
+
qargs = (options.rdata_name.split('/', 1))
|
|
296
|
+
|
|
297
|
+
results = client.query_rdata_name(*qargs, before=options.before, after=options.after)
|
|
298
|
+
fmt_func = rdata_to_text
|
|
299
|
+
elif options.rdata_ip:
|
|
300
|
+
results = client.query_rdata_ip(options.rdata_ip, before=options.before, after=options.after)
|
|
301
|
+
fmt_func = rdata_to_text
|
|
302
|
+
else:
|
|
303
|
+
parser.print_help()
|
|
304
|
+
sys.exit(1)
|
|
305
|
+
|
|
306
|
+
if options.json:
|
|
307
|
+
fmt_func = json.dumps
|
|
308
|
+
|
|
309
|
+
try:
|
|
310
|
+
if options.sort:
|
|
311
|
+
results = list(results)
|
|
312
|
+
if len(results) > 0:
|
|
313
|
+
if options.sort not in results[0]:
|
|
314
|
+
sort_keys = results[0].keys()
|
|
315
|
+
sort_keys.sort()
|
|
316
|
+
sys.stderr.write('dnsdb_query: invalid sort key "%s". valid sort keys are %s\n' % (options.sort, ', '.join(sort_keys)))
|
|
317
|
+
sys.exit(1)
|
|
318
|
+
results.sort(key=lambda r: r[options.sort], reverse=options.reverse)
|
|
319
|
+
for res in results:
|
|
320
|
+
sys.stdout.write('%s\n' % fmt_func(res))
|
|
321
|
+
except QueryError as e:
|
|
322
|
+
print(e.message, file=sys.stderr)
|
|
323
|
+
sys.exit(1)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
if __name__ == '__main__':
|
|
327
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
# import pprint
|
|
7
|
+
|
|
8
|
+
copyright = """
|
|
9
|
+
Copyright 2019 (C) by Aaron Kaplan <aaron@lo-res.org>, all rights reserved.
|
|
10
|
+
This file is part of the ransomwarecoindDB project and licensed under the AGPL 3.0 license
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = 0.1
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
baseurl = "https://ransomcoindb.concinnity-risks.com/api/v1/"
|
|
17
|
+
user_agent = "ransomcoindb client via python-requests/%s" % requests.__version__
|
|
18
|
+
|
|
19
|
+
urls = {'BTC': {'btc': baseurl + 'bin2btc/',
|
|
20
|
+
'md5': baseurl + 'bin2btc/md5/',
|
|
21
|
+
'sha1': baseurl + 'bin2btc/sha1/',
|
|
22
|
+
'sha256': baseurl + 'bin2btc/sha256/',
|
|
23
|
+
},
|
|
24
|
+
'XMR': {'xmr': baseurl + 'bin2crypto/XMR/',
|
|
25
|
+
'md5': baseurl + 'bin2crypto/XMR/md5/',
|
|
26
|
+
'sha1': baseurl + 'bin2crypto/XMR/sha1/',
|
|
27
|
+
'sha256': baseurl + 'bin2crypto/XMR/sha256/',
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_data_by(coin: str, key: str, value: str, api_key: str):
|
|
33
|
+
"""
|
|
34
|
+
Abstract function to fetch data from the bin2btc/{key} endpoint.
|
|
35
|
+
This function must be made concrete by generating a relevant function.
|
|
36
|
+
See below for examples.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# pprint.pprint("api-key: %s" % api_key)
|
|
40
|
+
|
|
41
|
+
headers = {'x-api-key': api_key, 'content-type': 'application/json'}
|
|
42
|
+
headers.update({'User-Agent': user_agent})
|
|
43
|
+
|
|
44
|
+
# check first if valid:
|
|
45
|
+
valid_coins = ['BTC', 'XMR']
|
|
46
|
+
valid_keys = ['btc', 'md5', 'sha1', 'sha256']
|
|
47
|
+
if coin not in valid_coins or key not in valid_keys:
|
|
48
|
+
logging.error("get_data_by_X(): not a valid key parameter. Must be a valid coin (i.e. from %r) and one of: %r" % (valid_coins, valid_keys))
|
|
49
|
+
return None
|
|
50
|
+
try:
|
|
51
|
+
|
|
52
|
+
url = urls[coin.upper()][key]
|
|
53
|
+
logging.debug("url = %s" % url)
|
|
54
|
+
if not url:
|
|
55
|
+
logging.error("Could not find a valid coin/key combination. Must be a valid coin (i.e. from %r) and one of: %r" % (valid_coins, valid_keys))
|
|
56
|
+
return None
|
|
57
|
+
r = requests.get(url + "%s" % (value), headers=headers)
|
|
58
|
+
except Exception as ex:
|
|
59
|
+
logging.error("could not fetch from the service. Error: %s" % str(ex))
|
|
60
|
+
|
|
61
|
+
if r.status_code != 200:
|
|
62
|
+
logging.error("could not fetch from the service. Status code: %s" %
|
|
63
|
+
r.status_code)
|
|
64
|
+
return r.json()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_bin2btc_by_btc(btc_addr: str, api_key: str):
|
|
68
|
+
""" Function to fetch the data from the bin2btc/{btc} endpoint """
|
|
69
|
+
return get_data_by('BTC', 'btc', btc_addr, api_key)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_bin2btc_by_md5(md5: str, api_key: str):
|
|
73
|
+
""" Function to fetch the data from the bin2btc/{md5} endpoint """
|
|
74
|
+
return get_data_by('BTC', 'md5', md5, api_key)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_bin2btc_by_sha1(sha1: str, api_key: str):
|
|
78
|
+
""" Function to fetch the data from the bin2btc/{sha1} endpoint """
|
|
79
|
+
return get_data_by('BTC', 'sha1', sha1, api_key)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_bin2btc_by_sha256(sha256: str, api_key: str):
|
|
83
|
+
""" Function to fetch the data from the bin2btc/{sha256} endpoint """
|
|
84
|
+
return get_data_by('BTC', 'sha256', sha256, api_key)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
""" Just for testing on the cmd line. """
|
|
89
|
+
to_btc = "1KnuC7FdhGuHpvFNxtBpz299Q5QteUdNCq"
|
|
90
|
+
api_key = os.getenv('api_key')
|
|
91
|
+
r = get_bin2btc_by_btc(to_btc, api_key)
|
|
92
|
+
print(r)
|
|
93
|
+
r = get_bin2btc_by_md5("abc", api_key)
|
|
94
|
+
print(r)
|
|
95
|
+
r = get_data_by('XMR', 'md5', "452878CD7", api_key)
|
|
96
|
+
print(r)
|
|
File without changes
|