Skip to content

Commit

Permalink
Merge pull request #297 from 0xswitch/develop
Browse files Browse the repository at this point in the history
New analyser : Google Vision API
  • Loading branch information
3c7 authored Jul 14, 2019
2 parents 4992953 + a54307a commit 67401d4
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 0 deletions.
30 changes: 30 additions & 0 deletions analyzers/GoogleVisionAPI/GoogleVisionAPI_WebDetection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "GoogleVisionAPI_WebDetection",
"version": "1.0.0",
"author": "CERT-LaPoste",
"url": "https://github.com/TheHive-Project/Cortex-Analyzers",
"license": "AGPL-V3",
"description": "Find look alike image via Google Cloud Vision API using the Web_Detection service ",
"dataTypeList": ["file", "url"],
"command": "GoogleVisionAPI/GoogleVisionAPI_WebDetection.py",
"baseConfig": "GoogleVisionAPI",
"config": {
"service": "get"
},
"configurationItems": [
{
"name": "api_key",
"description": "API key for this service",
"type": "string",
"multi": false,
"required": true
},
{
"name": "max_Result",
"description": "Maximum number of url to fetch",
"type": "string",
"multi": false,
"required": false
}
]
}
80 changes: 80 additions & 0 deletions analyzers/GoogleVisionAPI/GoogleVisionAPI_WebDetection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/python3
#coding:utf-8

from cortexutils.analyzer import Analyzer
from requests import post
from json import dumps, loads
from base64 import b64encode

class GoogleAPI_Vision(Analyzer):

def __init__(self):
Analyzer.__init__(self)
self.api_endpoint = "https://vision.googleapis.com/v1/images:annotate"

def make_api_call(self, url: str, query: str, api_key: str, https_proxy: str, maxResults: int, datatype: str, file=None) -> dict:

header = {
"Content-Type" : "application/json"
}

data = {
"requests": [{
"image": {
"source": {
"imageUri": query
}
},
"features": [{
"type": "WEB_DETECTION",
"maxResults": maxResults
}]
}]
}

if datatype == "file":
try:
query = b64encode(open(file, "rb").read()).decode("utf-8")
except FileNotFoundError:
self.error("Error while reading provided file")
else:
del data["requests"][0]["image"]["source"]
data["requests"][0]["image"]["content"] = query

try:
api_answser = loads(post(url + "?key=" + api_key, data=dumps(data), headers=header, proxies=https_proxy).text)
except ValueError:
self.error("Cannot parse JSON answer from server")
else:
return api_answser

def get_artifacts(self, google_results: str) -> list:
return [ item["url"] for item in google_results['responses'][0]["webDetection"]["pagesWithMatchingImages"]]

def run(self):
query = self.getData()

if query is None:
self.error("You must provide a file or a valid url to this image")

api_key = self.getParam("config.api_key")
if api_key is None:
self.error("You need an API key for Google Vision API")

https_proxy = { "https" : self.getParam("config.proxy_https") }
maxResults = self.getParam("config.max_Result")
maxResults = maxResults if maxResults is not None else 100

answer = self.make_api_call(self.api_endpoint, query, api_key, https_proxy, maxResults, self.data_type, file=self.getParam("file"))
self.report({ 'api_full_report' : answer })

def summary(self, raw):

number_of_image_found = self.build_taxonomy("info", "GoogleVisionAPI", "pagesWithMatchingImages", str(len(raw["api_full_report"]["responses"][0]["webDetection"]["pagesWithMatchingImages"])))
number_of_look_alike = self.build_taxonomy("info", "GoogleVisionAPI", "visuallySimilarImages", str(len(raw["api_full_report"]["responses"][0]["webDetection"]["visuallySimilarImages"])))

return { "taxonomies" : [number_of_look_alike, number_of_image_found] }


if __name__ == "__main__":
GoogleAPI_Vision().run()
2 changes: 2 additions & 0 deletions analyzers/GoogleVisionAPI/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cortexutils
requests
72 changes: 72 additions & 0 deletions thehive-templates/GoogleVisionAPI_WebDetection_1_0_0/long.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!-- Success -->
<div class="panel panel-primary" ng-if="content.api_full_report.responses[0].webDetection.pagesWithMatchingImages.length > 0">
<div class="panel-heading">
Pages with matching images
</div>
<div class="panel-body">
<dl class="dl-horizontal" >
<strong>Number of pages found : </strong> {{ content.api_full_report.responses[0].webDetection.pagesWithMatchingImages.length }}
<dd>
<div ng-repeat="pages in content.api_full_report.responses[0].webDetection.pagesWithMatchingImages | limitTo:50">
<span class="wrap"><a ng-href="{{ pages.url }}" target="_blank">{{pages.pageTitle }}</a></span>
</div>
</dd>
</dl>
</div>
</div>

<div class="panel panel-primary" ng-if="content.api_full_report.responses[0].webDetection.visuallySimilarImages.length > 0">
<div class="panel-heading">
Visually Similar Images
</div>
<div class="panel-body">
<dl class="dl-horizontal" >
<strong>Number of similar image found : </strong> {{ content.api_full_report.responses[0].webDetection.visuallySimilarImages.length }}
<dd>
<div ng-repeat="similar in content.api_full_report.responses[0].webDetection.visuallySimilarImages | limitTo:50">
<span class="wrap"><a ng-href="{{ similar.url }}" target="_blank">{{similar.url }}</a></span>
</div>
</dd>
</dl>
</div>
</div>

<div class="panel panel-primary" ng-if="content.api_full_report.responses[0].webDetection.webEntities.length > 0">
<div class="panel-heading">
Web Entities
</div>
<div class="panel-body">
<dd>
<div ng-repeat="entities in content.api_full_report.responses[0].webDetection.webEntities | limitTo:50">
<span class="wrap" ng-if="entities.description.length >0"><strong>{{ entities.description }} : </strong>{{ entities.score }}</span>
</div>
</dd>
</div>
</div>

<!-- General error -->
<div class="panel panel-danger" ng-if="content.api_full_report.error">
<div class="panel-heading">
<strong>An error occured</strong>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt><i class="fa fa-warning"></i> {{ content.api_full_report.error.status }} :</dt>
<dd class="wrap">{{content.api_full_report.error.message}}</dd>
</dl>
</div>
</div>

<div class="panel panel-danger" ng-if="!content.success">
<div class="panel-heading">
<strong>An error occured</strong>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt><i class="fa fa-warning"></i> {{ content.errorMessage }} :</dt>
<dd class="wrap">{{content.input}}</dd>
</dl>
</div>
</div>


Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<span class="label" ng-repeat="t in content.taxonomies"
ng-class="{'info': 'label-info', 'safe': 'label-success',
'suspicious': 'label-warning',
'malicious':'label-danger'}[t.level]">
{{t.namespace}}:{{t.predicate}}={{t.value}}
</span>

0 comments on commit 67401d4

Please sign in to comment.