
بصمة استخباراتية مفتوحة المصدر موجهة نحو المنظمة وذات رأي، مستوحاة من recon-ng وMaltego.
إشعار
هذا المشروع مكتمل جزئيًا فقط ولم أقم بعد بتنفيذ العديد من الميزات الموصوفة في منشور المدونة التالي الذي كتبته: https://penafieljlm.com/2017/07/14/inquisitor/.
Inquisitor هي أداة بسيطة لجمع المعلومات عن الشركات والمؤسسات باستخدام مصادر الاستخبارات مفتوحة المصدر (OSINT). وهي مستوحاة بشكل كبير من طريقة عمل Maltego و recon-ng، وتقوم الأداة إلى حد كبير بإعادة تنفيذ بعض ميزات تلك الأدوات ولكنها تضيف طبقة إضافية من الدلالات القائمة على الرأي فوق أنواع الأصول لإنشاء سير عمل سهل الاستخدام.
الميزات الرئيسية لـ Inquisitor تشمل:
المفهوم الكامل لـ Inquisitor يدور حول فكرة استخراج المعلومات من المصادر المفتوحة بناءً على ما هو معروف بالفعل عن المؤسسة المستهدفة. في سياق Inquisitor تسمى هذه "التحويلات (transforms)". قد يتم أيضًا استرداد المعلومات ذات الصلة فورًا من أصل معروف بناءً على البيانات الوصفية القابلة للاسترداد أيضًا من المصادر المفتوحة مثل whois وسجلات الإنترنت.
يتم مناقشة المفاهيم بمزيد من التفصيل في مقالة المدونة هذه: https://penafieljlm.com/2017/07/14/inquisitor/
لتثبيت Inquisitor، ما عليك سوى استنساخ المستودع، والدخول إليه، وتنفيذ برنامج التثبيت.``` pip install Cython click git clone [email protected]:penafieljlm/inquisitor.git cd inquisitor python setup.py install
## الاستخدام
يحتوي Inquisitor على خمسة أوامر أساسية تشمل `scan` و`status` و`classify` و`dump` و`visualize`.```
usage: inq [-h] {scan,status,classify,dump,visualize} ...
optional arguments:
-h, --help show this help message and exit
command:
{scan,status,classify,dump,visualize}
The action to perform.
scan Search OSINT sources for intelligence based on known
assets belonging to the target.
status Prints out the current status of the specified
intelligence database.
classify Classifies an existing asset as either belonging or
not belonging to the target. Adds a new asset with the
specified classification if none is present.
dump Dumps the contents of the database into a JSON file
visualize Create a D3.js visualization based on the contents of
the specified intelligence database.
في وضع المسح، تقوم الأداة بتشغيل جميع التحويلات المتاحة لجميع الأصول الموجودة في قاعدة بيانات الاستخبارات الخاصة بك. تأكد من إنشاء مفاتيح API لمصادر OSINT المختلفة الموضحة أدناه وتوفيرها للبرنامج النصي حتى لا يتم تخطي التحويلات التي تستخدم تلك المصادر. أيضًا، تأكد من تغذية قاعدة بيانات الاستخبارات الخاصة بك ببعض الأصول المستهدفة المملوكة المعروفة باستخدام الأمر classify أولاً، لأنه إذا كانت قاعدة البيانات لا تحتوي على أي أصول مملوكة، فلن يكون هناك شيء لتحويله.```
usage: inq scan [-h] [--google-dev-key GOOGLE_DEV_KEY]
[--google-cse-id GOOGLE_CSE_ID]
[--google-limit GOOGLE_LIMIT]
[--shodan-api-key SHODAN_API_KEY]
[--shodan-limit SHODAN_LIMIT]
DATABASE
positional arguments: DATABASE The path to the intelligence database to use. If specified file does not exist, a new one will be created.
optional arguments: -h, --help show this help message and exit --google-dev-key GOOGLE_DEV_KEY Specifies the developer key to use to query Google Custom Search. Visit the Google APIs Console (http://code.google.com/apis/console) to get an API key. If notspecified, the script will simply skip asset transforms that involve Google Search. --google-cse-id GOOGLE_CSE_ID Specifies the custom search engine to query. Visit the Google Custom Search Console (https://cse.google.com/cse/all) to create your own Google Custom Search Engine. If not specified, the script will simply skip asset transforms that involve Google Search. --google-limit GOOGLE_LIMIT The number of pages to limit Google Search to. This is to avoid exhausting your daily quota. --shodan-api-key SHODAN_API_KEY Specifies the API key to use to query Shodan. Log into your Shodan account (https://www.shodan.io/) and look at the top right corner of the page in order to view your API key. If not specified, the script will simply skip asset transforms that involve Shodan. --shodan-limit SHODAN_LIMIT The number of pages to limit Shodan Search to. This is to avoid exhausting your daily quota.
### الحالة
في وضع الحالة، تقوم الأداة بطباعة ملخص سريع لحالة قاعدة بيانات المسح الخاصة بك.```
usage: inq status [-h] [-s] DATABASE
positional arguments:
DATABASE The path to the intelligence database to use. If specified
file does not exist, a new one will be created.
optional arguments:
-h, --help show this help message and exit
-s, --strong Indicates if the status will be based on the strong ownership
classification.
في وضع التصنيف، ستتمكن من إضافة الأصول يدويًا وإعادة تصنيف الأصول الموجودة بالفعل في قاعدة بيانات الاستخبارات. يجب استخدام هذا الأمر لتزويد قاعدة بيانات الاستخبارات الخاصة بك بأصول الهدف المملوكة والمعروفة.``` usage: inq classify [-h] [-ar REGISTRANT [REGISTRANT ...]] [-ur REGISTRANT [REGISTRANT ...]] [-rr REGISTRANT [REGISTRANT ...]] [-ab BLOCK [BLOCK ...]] [-ub BLOCK [BLOCK ...]] [-rb BLOCK [BLOCK ...]] [-ah HOST [HOST ...]] [-uh HOST [HOST ...]] [-rh HOST [HOST ...]] [-ae EMAIL [EMAIL ...]] [-ue EMAIL [EMAIL ...]] [-re EMAIL [EMAIL ...]] [-al LINKEDIN [LINKEDIN ...]] [-ul LINKEDIN [LINKEDIN ...]] [-rl LINKEDIN [LINKEDIN ...]] DATABASE
positional arguments: DATABASE The path to the intelligence database to use. If specified file does not exist, a new one will be created.
optional arguments: -h, --help show this help message and exit -ar REGISTRANT [REGISTRANT ...], --accept-registrant REGISTRANT [REGISTRANT ...] Specifies a registrant to classify as accepted. -ur REGISTRANT [REGISTRANT ...], --unmark-registrant REGISTRANT [REGISTRANT ...] Specifies a registrant to classify as unmarked. -rr REGISTRANT [REGISTRANT ...], --reject-registrant REGISTRANT [REGISTRANT ...] Specifies a registrant to classify as rejected. -ab BLOCK [BLOCK ...], --accept-block BLOCK [BLOCK ...] Specifies a block to classify as accepted. -ub BLOCK [BLOCK ...], --unmark-block BLOCK [BLOCK ...] Specifies a block to classify as unmarked. -rb BLOCK [BLOCK ...], --reject-block BLOCK [BLOCK ...] Specifies a block to classify as rejected. -ah HOST [HOST ...], --accept-host HOST [HOST ...] Specifies a host to classify as accepted. -uh HOST [HOST ...], --unmark-host HOST [HOST ...] Specifies a host to classify as unmarked. -rh HOST [HOST ...], --reject-host HOST [HOST ...] Specifies a host to classify as rejected. -ae EMAIL [EMAIL ...], --accept-email EMAIL [EMAIL ...] Specifies a email to classify as accepted. -ue EMAIL [EMAIL ...], --unmark-email EMAIL [EMAIL ...] Specifies a email to classify as unmarked. -re EMAIL [EMAIL ...], --reject-email EMAIL [EMAIL ...] Specifies a email to classify as rejected. -al LINKEDIN [LINKEDIN ...], --accept-linkedin LINKEDIN [LINKEDIN ...] Specifies a LinkedIn Account to classify as accepted. -ul LINKEDIN [LINKEDIN ...], --unmark-linkedin LINKEDIN [LINKEDIN ...] Specifies a LinkedIn Account to classify as unmarked. -rl LINKEDIN [LINKEDIN ...], --reject-linkedin LINKEDIN [LINKEDIN ...] Specifies a LinkedIn Account to classify as rejected.
### تفريغ
في وضع التفريغ، ستتمكن من تفريغ محتويات قاعدة بيانات الاستخبارات إلى ملف JSON يمكن قراءته بواسطة الإنسان.```
usage: inq dump [-h] [-j FILE] [-a] DATABASE
positional arguments:
DATABASE The path to the intelligence database to use. If
specified file does not exist, a new one will be
created.
optional arguments:
-h, --help show this help message and exit
-j FILE, --json FILE The path to dump the JSON file to. Overwrites existing
files.
-a, --all Include rejected assets in dump.
في وضع التصور، ستتمكن من الحصول على تصور هرمي لمستودع Intelligence Repository.``` usage: inq visualize [-h] [-l] DATABASE
positional arguments: DATABASE The path to the intelligence database to use. If specified file does not exist, a new one will be created.
optional arguments: -h, --help show this help message and exit -l, --last Simply open the last visualization generated instead of creating a new one.
## سير العمل
الآن بعد أن تعرفت على الميزات الأساسية لـ Inquisitor، حان الوقت لتتعلم كيفية *استخدامها* فعليًا. تم تصميم Inquisitor مع مراعاة الخطوات التالية:
### التأسيس (Seeding)
في هذه الخطوة، لا تحتوي قاعدة بيانات الاستخبارات الخاصة بك على أي شيء بعد. سيتعين علينا البدء من مكان ما، لذا قم بتأسيس قاعدة البيانات بالأصول التي تعرف أنها تنتمي إلى مؤسستك المستهدفة. يمكنك القيام بذلك باستخدام الأمر `classify`.
### المسح (Scanning)
الآن بعد أن أصبحت قاعدة البيانات تحتوي على أصول معروفة بأنها تنتمي إلى مؤسستك المستهدفة. يمكنك بعد ذلك المتابعة بالمسح. يمكنك القيام بذلك باستخدام الأمر `scan`.
عندما تستدعي الأمر `scan` على قاعدة بيانات الاستخبارات الخاصة بك، يقوم Inquisitor بتشغيل طرق `transform` للأصول المصنفة على أنها `accepted`. بمجرد انتهاء المسح، ستحصل على أصول إضافية قد تنتمي إلى مؤسستك المستهدفة.
إذا لم تحصل على أي أصول جديدة، يمكنك إما تأسيس قاعدة بيانات الاستخبارات الخاصة بك بمعلومات جديدة، أو ببساطة المتابعة لإنهاء العملية بالانتقال إلى خطوة إعداد التقارير.
### التصنيف (Classifying)
بينما يقوم Inquisitor بتصنيف الأصول تلقائيًا نيابة عنك، قد يفتقد بعض الأصول التي تنتمي بالفعل إلى مؤسستك المستهدفة.
عند حدوث ذلك، سيتعين عليك التحقق من محتويات قاعدة البيانات وتصنيف الأصول يدويًا. عادةً، سترغب في الانتباه إلى أصول **المسجل (Registrant)** حيث لا توجد طريقة لتحديد الملكية تلقائيًا لهذا النوع من الأصول. كما أن معظم أنواع الأصول الأخرى تعتمد على تصنيف ملكية أصول المسجل لتحديد ما إذا كانت تنتمي إلى هدفك أم لا، لذا من الأفضل بالتأكيد الانتباه إلى أصول المسجل. بالإضافة إلى ذلك، لا تحصل على الكثير من أصول المسجل في المقام الأول، لذا لن يكون من الصعب فرزها.
### إعداد التقارير (Reporting)
يمكنك إنشاء تصور للأصول التي تنتمي إلى مؤسستك المستهدفة باستخدام الأمر `visualize` أو الأمر `dump`.
## عرض توضيحي
لدي عروض فيديو توضيحية للأداة وهي تعمل على الرابط التالي: https://drive.google.com/open?id=0B_O70BVu38TRclo5dWRBWkdTTWc
لم أتمكن من تسجيل تشغيل الأمر scan بالكامل لأن مسجل الشاشة المجاني الخاص بي يسجل فقط حتى 10 دقائق.
## التطوير
تم تخطيط مشروع Inquisitor بالتنسيق التالي:```
.
|-- README.md
|-- inquisitor
| |-- __init__.py
| |-- assets
| | |-- __init__.py
| | |-- block.py
| | |-- email.py
| | |-- host.py
| | |-- linkedin.py
| | `-- registrant.py
| |-- extractors
| | |-- __init__.py
| | `-- emails.py
| `-- sources
| |-- __init__.py
| |-- google_search.py
| `-- shodan_search.py
|-- inq
|-- report
| `-- index.html
|-- setup.py
`-- tests
|-- __init__.py
`-- test_inq.py
يحتوي على ثلاث وحدات رئيسية مسماة assets و extractors و sources. النص البرمجي الرئيسي يُسمى inq.
كمطور، ستكون مهتمًا في الغالب بإضافة أنواع جديدة من الأصول إلى النظام، لذا سيركز دليل المطور بشكل أساسي على ذلك.
قبل الانتقال إلى تنفيذ فئات الأصول فعليًا، نحتاج أولاً إلى فهم كيفية التفاعل مع قاعدة بيانات الاستخبارات لأننا سنتفاعل معها عندما نستمد الأصول ذات الصلة من فئات الأصول الخاصة بنا.
كود المصدر لقاعدة بيانات الاستخبارات مخزَّن في ملف inquisitor/__init__.py. الاسم الفعلي للغلاف المنطقي لقاعدة بيانات الاستخبارات يُسمى IntelligenceRepository.
ما عليك سوى استدعاء الدالة IntelligenceRepository.get_asset_string من فئات الأصول، لأن إلحاق أصول جديدة بقاعدة بيانات الاستخبارات هو من مسؤولية وحدة scan في النص البرمجي inq. ستستخدم هذه الدالة في الغالب لإنشاء مثيلات للأصول أو استرجاعها من قاعدة البيانات إذا كانت موجودة. هذه الدالة مهمة عند إرجاع الأصول من دالتي related و transform في فئات الأصول الخاصة بك، لأن إنشاء كائنات أصول جديدة مكلف حيث أن بعضها يستخدم موارد الشبكة أثناء التهيئة.```
Function
IntelligenceRepository.get_asset_string(asset_type, identifier, create=False, store=False)
Description
Retrieves the primary key and asset object for the asset with the provided
type and identifier.
Parameters
asset_type: class, required
The type of the asset to retrieve from the Intelligence Database. You
will actually have to pass the class object of the asset type you want
to retrieve.
identifier: any, required
The identifier of the asset to retrieve. Consider the identifier as the
unique attribute of an asset object. As for which attribute is to be
used to identify an asset, it depends on the contents of the OBJECT_ID
variable in the asset module.
create: bool, optional, default=False
When no matching asset object is found, a new one will be created and
returned if this parameter is set to True. The new asset will not
necessarily be stored in the Intelligence Database unless specified
using the "store" parameter. However, I suggest you do not do this as
adding assets to the Intelligence Database is the responsibility of
another module.
store: bool, optional, default=False
When a new asset is created when none is found, the new one will be
stored in the Intelligence Database. As said previously, I suggest that
you do not do this as adding assets to the Intelligence Database is the
responsibility of another module.
Returns
A two-element tuple where the first element is the database primary key of
the element returned, and the second element is the deserialized asset
object retrieved from the database.
None if the asset was not found.
If the asset was not found and the create flag was set to True, the primary
key member of the tuple will be set to None.
### الأصول
لإنشاء نوع أصل جديد، قم بإنشاء ملف جديد داخل الدليل `inquisitor/assets` والصق الكود الأساسي التالي بالداخل:```python
import inquisitor.assets
class ASSET_NAMEValidateException(Exception):
pass
def canonicalize(ASSET_IDENTIFIER):
return ASSET_IDENTIFIER
def main_classify_args(parser):
parser.add_argument(
'-aASSET_NAME_LETTER', '--accept-ASSET_NAME',
metavar='ASSET_NAME',
type=canonicalize,
nargs='+',
help='Specifies a ASSET_NAME to classify as accepted.',
dest='ASSET_NAMEs_accepted',
default=list(),
)
parser.add_argument(
'-uASSET_NAME_LETTER', '--unmark-ASSET_NAME',
metavar='ASSET_NAME',
type=canonicalize,
nargs='+',
help='Specifies a ASSET_NAME to classify as unmarked.',
dest='ASSET_NAMEs_unmarked',
default=list(),
)
parser.add_argument(
'-rASSET_NAME_LETTER', '--reject-ASSET_NAME',
metavar='ASSET_NAME',
type=canonicalize,
nargs='+',
help='Specifies a ASSET_NAME to classify as rejected.',
dest='ASSET_NAME_rejected',
default=list(),
)
def main_classify_canonicalize(args):
accepted = set(args.ASSET_NAMEs_accepted)
unmarked = set(args.ASSET_NAMEs_unmarked)
rejected = set(args.ASSET_NAME_rejected)
redundant = set.intersection(accepted, unmarked, rejected)
if redundant:
raise ValueError(
('Conflicting classifications for ASSET_NAMEs '
': {}').format(list(redundant))
)
accepted = set([canonicalize(a) for a in accepted])
unmarked = set([canonicalize(a) for a in unmarked])
rejected = set([canonicalize(a) for a in rejected])
return (accepted, unmarked, rejected)
class ASSET_NAME(inquisitor.assets.Asset):
def __init__(self, ASSET_IDENTIFIER, owned=None):
super(self.__class__, self).__init__(owned=owned)
self.ASSET_IDENTIFIER = canonicalize(ASSET_IDENTIFIER)
# TODO: Perform other initialization actions here
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return self.ASSET_IDENTIFIER == other.ASSET_IDENTIFIER
def related(self, repo):
# Prepare the results
results = set()
# TODO: Create related assets here based on the attributes of this asset
# Return the results
return results
def transform(self, repo, sources):
# Prepare the results
assets = set()
# Google Transforms
if sources.get('google'):
subassets = self.cache_transform_get('google', repo)
if not subassets:
# Acquire API
google = sources['google']
# TODO: Perform Google queries here and the results to 'subassets'
# Cache The Transform
self.cache_transform_store('google', subassets)
assets.update(subassets)
# Shodan Transforms
if sources.get('shodan'):
subassets = self.cache_transform_get('shodan', repo)
if not subassets:
# Acquire API
shodan = sources['shodan']
# TODO: Perform Google queries here and the results to 'subassets'
# Cache The Transform
self.cache_transform_store('shodan', subassets)
assets.update(subassets)
# Return the results
return assets
def is_owned(self, repo):
if self.owned:
return True
# TODO: Automatically determine ownership based on repo contents
return False
def parent_asset(self, repo):
# TODO: Return parent asset based on repo contents
return None
REPOSITORY = 'ASSET_REPOSITORY'
ASSET_CLASS = ASSET_NAME
OBJECT_ID = 'ASSET_IDENTIFIER'
الآن استبدل السلاسل التالية بالقيم المناسبة
ASSET_NAME : الاسم الصحيح لأصولك (مثال: المسجّل، المضيف، إلخ)ASSET_IDENTIFIER : اسم سمة المعرف الخاصة بأصولكASSET_NAME_LETTER : الحرف الأول من اسم أصولك بحرف صغيرASSET_REPOSITORY : صيغة الجمع لاسم أصولك بأحرف صغيرةأخيرًا، في ملف inquisitor/__init__.py، قم بتسجيل أصولك في قائمة ASSET_MODULES. تأكد من استيراد الأصول الجديدة من الملف المعني.
تهانينا! عند هذه النقطة، أصبح لديك الآن نوع أصول جديد قيد العمل!
ومع ذلك، ستحتاج إلى تنفيذ الطرق التالية للتأكد من ربط أصولك بأنواع الأصول الأخرى:``` Function
related
Description
Returns the set of assets directly related to the asset in question (i.e.
those that can be derived without querying a search engine).
When creating asset objects, make sure you use the
IntelligenceRepository.get_asset_string method instead of instatiating a
new one your self so the asset can be returned from the repository if it
exists.
Set the create flag to True when calling the method in question in order
to return a new object when one isn't found.
Set the store flag to False as appending assets is the job of another
module.
Parameters
repo: IntelligenceRepository
The Intelligence Repository that is being used in the current context.
Returns
Set of assets directly related to the asset in question.
الرجاء تزويدي بنص الماركدون المراد ترجمته.```
Function
transform
Description
Returns the set of assets potentially related to the asset in question
(i.e. those that can be derived by querying a search engine).
You may access search engine objects through the provided sources
parameter.
Each search engine object has a transform method which automatically
creates asset objects for you. You just need to provide it the repository
and your query string, and then append the objects it returns to the set
of assets to be returned by your asset's transform method.
Parameters
repo: IntelligenceRepository
The Intelligence Repository that is being used in the current context.
sources: dict
The list of search engine objects that are available for use.
Returns
Set of assets potentially related to the asset in question.
AWS - EC2 بيانات المستخدم
-e ec2_userdata-req=``` Function
is_owned
Description
Determines if there is high confidence that this asset does indeed belong
to the target. Usually checks for any "strong" classification tag first by
looking at the contents of the "owned" variable, before performing
automatic evaluation.
Automatic evaluation depends on what type of asset you're writing. For
example, for a Host asset, the secondary sources of determining ownership
would include looking if its registrant is owned by the target, if it's
parent domain is owned by the target. etc.
Parameters
repo: IntelligenceRepository
The Intelligence Repository that is being used in the current context.
Returns
True it is determined with high confidence that this asset does indeed
belong to the target.
INPUT:```
Function
parent_asset
Description
Returns the asset object that is considered the parent of this asset
object.
Parameters
repo: IntelligenceRepository
Returns
The asset object that this asset falls under (e.g. a Block is under a
Registrant, a Host is under a Block, a Host is under another Host, an Email
is under a Host, etc. This is primarily used for visualization.
بعد تنفيذ الطرق المذكورة أعلاه، تأكد من تعيين المتغيرات REPOSITORY و ASSET_CLASS و OBJECT_ID في أسفل الكود المصدري لأصولك.
وضع المسح الضوئي لم يتم اختباره بالكامل بسبب الحصص المتعلقة بمحركات البحث المعنية. أيضًا، تم إنشاء هذا المشروع على عجل كجزء من هاكاثون استمر لمدة أسبوع، لذلك قد يكون هناك الكثير من المشكلات المنتشرة. يُرجى إنشاء تذكرة مشكلة أو الاتصال بي على البريد الإلكتروني [email protected] إذا وجدت خطأ أو كان لديك بعض الأسئلة.
هذا العمل مشتق من الأساليب التي نفذتها أدوات Maltego و recon-ng للاستخبارات مفتوحة المصدر. لقد قمت بتكملة هذه الأساليب بأفكار إما أنها معرفة شائعة بالفعل (على سبيل المثال، يخبرك whois بمن هو مالك النطاق، والنطاقات الفرعية مملوكة لنفس المؤسسة التي تمتلك النطاق الأب - كما هو موضح في هجمات تخمين أسماء النطاقات، والمؤسسات هي سلطة على أسماء النطاقات التي تمتلكها، وما إلى ذلك)، أو أصلية وقد تم تصورها من قبلي في وقتي الشخصي كجزء من هوايتي (على سبيل المثال، تقييمات القبول، والتحويلات المختلفة، ووراثة التصنيف، وما إلى ذلك).
لا يوجد جزء من هذا العمل مشتق من أي عمل قمت به لأي صاحب عمل في الماضي. تمت كتابة المشروع بأكمله، بما في ذلك إثبات المفهوم، من الصفر وتم تعزيزه بأفكار من مجتمع أمن المعلومات.