Skip to content

Commit 157b68d

Browse files
committed
Merged PR smicallef#1879
1 parent 331fd7e commit 157b68d

File tree

2 files changed

+247
-0
lines changed

2 files changed

+247
-0
lines changed

Dockerfile.new

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# Spiderfoot Dockerfile
3+
#
4+
# http://www.spiderfoot.net
5+
#
6+
# Written by: Michael Pellon <[email protected]>
7+
# Updated by: Chandrapal <[email protected]>
8+
# Updated by: Steve Micallef <[email protected]>
9+
# Updated by: Steve Bate <[email protected]>
10+
# -> Inspired by https://github.com/combro2k/dockerfiles/tree/master/alpine-spiderfoot
11+
#
12+
# Usage:
13+
#
14+
# sudo docker build -t spiderfoot .
15+
# sudo docker run -p 5001:5001 --security-opt no-new-privileges spiderfoot
16+
#
17+
# Using Docker volume for spiderfoot data
18+
#
19+
# sudo docker run -p 5001:5001 -v /mydir/spiderfoot:/var/lib/spiderfoot spiderfoot
20+
#
21+
# Using SpiderFoot remote command line with web server
22+
#
23+
# docker run --rm -it spiderfoot sfcli.py -s http://my.spiderfoot.host:5001/
24+
#
25+
# Running spiderfoot commands without web server (can optionally specify volume)
26+
#
27+
# sudo docker run --rm spiderfoot sf.py -h
28+
#
29+
# Running a shell in the container for maintenance
30+
# sudo docker run -it --entrypoint /bin/sh spiderfoot
31+
#
32+
# Running spiderfoot unit tests in container
33+
#
34+
# sudo docker build -t spiderfoot-test --build-arg REQUIREMENTS=test/requirements.txt .
35+
# sudo docker run --rm spiderfoot-test -m pytest --flake8 .
36+
37+
FROM kalilinux/kali-rolling:latest AS build
38+
ARG REQUIREMENTS=requirements.txt
39+
#RUN apt update && apt install -y gcc git curl python3 python3-dev swig libtinyxml-dev \
40+
# python3-dev musl-dev openssl-dev libffi-dev libxslt-dev libxml2-dev jpeg-dev \
41+
# openjpeg-dev zlib-dev cargo rust
42+
RUN python3 -m venv /opt/venv
43+
RUN apt update && apt install -y gcc git curl python3 python3-dev swig libtinyxml-dev \
44+
python3-dev musl-dev libssl-dev libffi-dev libxslt-dev libxml2-dev libjpeg-dev \
45+
libopenjp2-7-dev zlib1g-dev cargo rust-all
46+
RUN python3 -m venv /opt/venv
47+
ENV PATH="/opt/venv/bin":$PATH
48+
COPY $REQUIREMENTS requirements.txt ./
49+
RUN ls
50+
RUN echo "$REQUIREMENTS"
51+
RUN pip3 install -U pip
52+
RUN pip3 install -r "$REQUIREMENTS"
53+
54+
55+
56+
FROM kalilinux/kali-rolling:latest
57+
WORKDIR /home/spiderfoot
58+
59+
# Place database and logs outside installation directory
60+
ENV SPIDERFOOT_DATA /var/lib/spiderfoot
61+
ENV SPIDERFOOT_LOGS /var/lib/spiderfoot/log
62+
ENV SPIDERFOOT_CACHE /var/lib/spiderfoot/cache
63+
64+
# Run everything as one command so that only one layer is created
65+
RUN apt update && apt -y install python3 musl openssl libxslt tinyxml libxml2 jpeg zlib openjpeg \
66+
&& adduser -u 99 -G users -h /home/spiderfoot -s /sbin/nologin \
67+
-g "SpiderFoot User" -D spiderfoot \
68+
&& rm -rf /var/cache/apt/* \
69+
&& rm -rf /lib/apt/db \
70+
&& rm -rf /root/.cache \
71+
&& mkdir -p $SPIDERFOOT_DATA || true \
72+
&& mkdir -p $SPIDERFOOT_LOGS || true \
73+
&& mkdir -p $SPIDERFOOT_CACHE || true \
74+
&& chown spiderfoot:users $SPIDERFOOT_DATA \
75+
&& chown spiderfoot:users $SPIDERFOOT_LOGS \
76+
&& chown spiderfoot:users $SPIDERFOOT_CACHE
77+
78+
COPY . .
79+
COPY --from=build /opt/venv /opt/venv
80+
ENV PATH="/opt/venv/bin:$PATH"
81+
82+
USER spiderfoot
83+
84+
EXPOSE 5001
85+
86+
# Run the application.
87+
ENTRYPOINT ["/opt/venv/bin/python"]
88+
CMD ["sf.py", "-l", "0.0.0.0:5001"]

modules/sfp_deepinfo.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# -*- coding: utf-8 -*-
2+
# -------------------------------------------------------------------------------
3+
# Name: sfp_deepinfo
4+
# Purpose: Query Deepinfo using their API
5+
#
6+
# Author: Ceylan Bozogullarindan
7+
#
8+
# Created: 16/04:/2022
9+
# Copyright: (c) Deepinfo 2023
10+
# Licence: GPL
11+
# -------------------------------------------------------------------------------
12+
13+
import json
14+
import time
15+
from spiderfoot import SpiderFootEvent, SpiderFootPlugin
16+
17+
class sfp_deepinfo(SpiderFootPlugin):
18+
meta = {
19+
'name': "Deepinfo",
20+
'summary': "Obtain Passive DNS and other information from Deepinfo",
21+
'flags': ["apikey"],
22+
'useCases': ["Investigate", "Passive"],
23+
'categories': ["Search Engines"],
24+
'dataSource': {
25+
'website': "https://deepinfo.com/",
26+
'model': "COMMERCIAL_ONLY",
27+
'references': [
28+
"https://docs.deepinfo.com/docs/getting-started"
29+
],
30+
'apiKeyInstructions': [
31+
"Visit https://deepinfo.info/request-demo",
32+
"Request a demo account",
33+
"Navigate to https://platform.deepinfo.com/app/settings/organization/api-keys",
34+
"The API key is listed under 'API Keys'"
35+
],
36+
'favIcon': "https://ik.imagekit.io/deepinfo/test/favicon/favicon-96x96.png",
37+
'logo': "https://ik.imagekit.io/deepinfo/test/favicon/favicon-96x96.png",
38+
'description': "Deepinfo provides relevant data and insights that empower "
39+
"cybersecurity professionals by providing access to an extensive database and reliable indicators."
40+
"Deepinfo has the data you need to understand what's going on on the Internet, we are dealing with "
41+
"terabytes of data, hundreds of data sources, billions of lines of raw data.",
42+
}
43+
}
44+
45+
# Default options
46+
opts = {
47+
"api_key": "",
48+
}
49+
50+
# Option descriptions
51+
optdescs = {
52+
"api_key": "Deepinfo API key.",
53+
}
54+
55+
# Be sure to completely clear any class variables in setup()
56+
# or you run the risk of data persisting between scan runs.
57+
58+
results = None
59+
errorState = False
60+
61+
def setup(self, sfc, userOpts=dict()):
62+
self.sf = sfc
63+
self.results = self.tempStorage()
64+
65+
# Clear / reset any other class member variables here
66+
# or you risk them persisting between threads.
67+
68+
for opt in list(userOpts.keys()):
69+
self.opts[opt] = userOpts[opt]
70+
71+
# What events is this module interested in for input
72+
def watchedEvents(self):
73+
return ["DOMAIN_NAME"]
74+
75+
# What events this module produces
76+
def producedEvents(self):
77+
return ["DOMAIN_NAME",
78+
"INTERNET_NAME"
79+
]
80+
81+
# Search Deepinfo
82+
def query(self, qry, page=1, accum=None):
83+
url = f"https://api.deepinfo.com/v1/discovery/subdomain-finder?domain={qry}&page={page}"
84+
request = None
85+
headers = {"apikey": self.opts['api_key']}
86+
res = self.sf.fetchUrl(url,
87+
useragent="SpiderFoot", headers=headers,
88+
postData=request)
89+
90+
if res['code'] not in ["200"]:
91+
self.error("Deepinfo API key seems to have been rejected or you have exceeded usage limits for the month.")
92+
self.errorState = True
93+
return None
94+
95+
if res['content'] is None:
96+
self.info("No Deepinfo info found for " + qry)
97+
return None
98+
99+
try:
100+
info = json.loads(res['content'])
101+
self.info("result_count {0}, page {1}".format(info.get("result_count"), page))
102+
if info.get("result_count", 0) > 100:
103+
domains = [item.get("punycode", "") for item in info.get("results", [])]
104+
if len(domains) >= 100:
105+
# Avoid throttling
106+
time.sleep(1)
107+
if accum:
108+
accum.extend(domains)
109+
else:
110+
accum = domains
111+
return self.query(qry, page + 1, accum)
112+
else:
113+
# We are at the last page
114+
accum.extend(domains)
115+
return accum
116+
else:
117+
return info.get('results', [])
118+
except Exception as e:
119+
self.error("Error processing JSON response from Deepinfo: " + str(e))
120+
return None
121+
122+
# Handle events sent to this module
123+
def handleEvent(self, event):
124+
eventName = event.eventType
125+
srcModuleName = event.module
126+
eventData = event.data
127+
128+
if self.errorState:
129+
return
130+
131+
self.debug(f"Received event, {eventName}, from {srcModuleName}")
132+
133+
if self.opts['api_key'] == "":
134+
self.error("You enabled sfp_deepinfo but did not set an API uid/secret!")
135+
self.errorState = True
136+
return
137+
138+
# Don't look up stuff twice
139+
if eventData in self.results:
140+
self.debug(f"Skipping {eventData}, already checked.")
141+
return
142+
143+
self.results[eventData] = True
144+
145+
if eventName in ["DOMAIN_NAME"]:
146+
domain = eventData
147+
rec = self.query(domain)
148+
myres = list()
149+
if rec is not None:
150+
for h in rec:
151+
if h == "":
152+
continue
153+
if h.lower() not in myres:
154+
myres.append(h.lower())
155+
else:
156+
continue
157+
e = SpiderFootEvent("INTERNET_NAME", h,
158+
self.__name__, event)
159+
self.notifyListeners(e)

0 commit comments

Comments
 (0)