Google Safe Browsing API

Max Kleiner
3 min readSep 5, 2022

Build a Post

The Google Safe Browsing API is a service that enables applications to check URLs against the Google’s lists of suspected phishing and postulated malware pages.

Do some work like data download on the @cloudshell
Enable the API

First you need an APIKey and an Enabler to this API otherwise:

GPost: Failed at getting response:403{
“error”: {
“code”: 403,
“message”: “Safe Browsing API has not been used in project 338972382324 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/safebrowsing.googleapis.com/overview?project=338972382324 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.”,
“status”: “PERMISSION_DENIED”,
“details”: [
{
“@type”: “type.googleapis.com/google.rpc.Help”,
“links”: [
{
“description”: “Google developers console API activation”,
“url”: “https://console.developers.google.com/apis/api/safebrowsing.googleapis.com/overview?project=338972382324”
}]},{
“@type”: “type.googleapis.com/google.rpc.ErrorInfo”,
“reason”: “SERVICE_DISABLED”,
“domain”: “googleapis.com”,
“metadata”: {
“consumer”: “projects/338972382324”,
“service”: “safebrowsing.googleapis.com”
} } ] } }

Benchmarking and access control

The response body includes the match information (the list names and the URLs found on those lists, the metadata, if available, and the cache durations). For more details, see the threatMatches.find response body and the explanations that follow the code example.

Note: If there are no matches (that is, if none of the URLs specified in the request are found on any of the lists specified in a request), the HTTP POST response simply returns an empty object in the response body.

1..66

procedure setTestData;
begin
JTESTDATA:=
'{ '+LF+
'"client": { '+LF+
' "clientId": "TestClient4", '+LF+
' "clientVersion": "1.1" '+LF+'}, '+LF+
'"threatInfo": { '+LF+
' "threatTypes": ["MALWARE", "SOCIAL_ENGINEERING"],'+LF+
' "platformTypes": ["LINUX"], '+LF+
' "threatEntryTypes": ["URL"], '+LF+
' "threatEntries": [ '+LF+
' {"url": "%s"} '+LF+
' ] '+LF+' } '+LF+'}';
end;

function getPostGoogleAPI(feedstream, aApikey, tolang: string): string;
var Url,aAPI_KEY, source: string;
jo, locate: TJSONObject; httpReq,hr: Olevariant; strm: TStringStream;
begin
//setTestData before;
httpReq:= CreateOleObject('WinHttp.WinHttpRequest.5.1');
// Open HTTPs connection.
try
hr:= httpReq.Open('POST',
'https://safebrowsing.googleapis.com/v4/threatMatches:find?key='
+aApikey, false);

httpReq.setRequestheader('user-agent',SUSERAGENT );
httpReq.setRequestheader('content-type','application/json');
if
hr= S_OK then HttpReq.Send(format(JTESTDATA,[feedstream]));
//writeln(format(JTESTDATA,[feedstream]));
If
HttpReq.Status = 200 Then
result:= HttpReq.responseText
Else
result:= 'Failed at getting
response:'+itoa(HttpReq.Status)+HttpReq.responseText;
//writeln('debug response '+HttpReq.GetAllResponseHeaders);
finally
httpreq:= unassigned;
end;
end;

const URLMALWARE ='http://malware.testing.google.test/testing/malware/';
writeln('GPost: '+getPostGoogleAPI(URLMALWARE, GoogleApiKey,''));

>>> GPost: {"matches": [{"threatType": "MALWARE","platformType": "LINUX","threat": {"url": "http://malware.testing.google.test/testing/malware/"},"cacheDuration": "300s","threatEntryType": "URL"}]}

{"client":{"clientId":"TestClient4","clientVersion":"1.1"},"threatInfo":{"threatTypes":["MALWARE","SOCIAL_ENGINEERING"],"platformTypes":["LINUX"],"threatEntryTypes":["URL"],"threatEntries":[{"url":"%s"}]}}

GPost: {}

Early binding with ALHTTPClient

http://www.softwareschule.ch/examples/alhttpclient2.txt

The matches object lists the names of the Safe Browsing lists and the URLs—if there is match. In the example, two URLs (urltocheck1.org and urltocheck2.org) were found on one of the Safe Browsing lists (MALWARE/WINDOWS/URL) so the matching information is returned. The third URL (urltocheck3.org) was not found on either list, so no information is returned for this URL postulate:

1..40

function TALHTTPClient_Post5GoogleAPI(aUrl: AnsiString;
feedstream, aapiKey: string;
aResponseContentStream:TStream;
aResponseContentHeader:TALHTTPResponseHeader):string;
Var FRequestHeader: TALHTTPRequestHeader; aPoststream: TStream;
begin
with
TALWininetHttpClient.create do begin
Url:= aURL + aApikey;
RequestMethod:= HTTPmt_Post; //HTTPrm_Post;
RequestHeader.UserAgent:= SUSERAGENT;
RequestHeader.ContentType:= 'application/json';
//LHttpClient.RequestHeader.RawHeaderText:='
try
aPoststream:= TStringStream.create(format(JTESTDATA,[feedstream]));
result:= Post3(Url, aPoststream); //overload;
finally
Free;
aPostStream.Free;
end;
end; //with
end;
writeln('GPost2: '+
TALHTTPClient_Post5GoogleAPI(URL_SAFEBROWSING,URLMALWARE,GoogleApiKey,Nil,Nil));

>>> GPost2: {
"matches": ["threatType": "MALWARE","platformType": "LINUX","threat": {"url": "http://malware.testing.google.test/testing/malware/","cacheDuration": "300s","threatEntryType": "URL"}]}

Metadata

The threatEntryMetadata field is optional and provides additional information about the threat match. Currently, metadata is available for the MALWARE/WINDOWS/URL Safe Browsing list (see Metadata).

Cache durations

The cacheDuration field indicates the amount of time the URL must be considered unsafe (see Caching).

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Max Kleiner
Max Kleiner

Written by Max Kleiner

Max Kleiner's professional environment is in the areas of OOP, UML and coding - among other things as a trainer, developer and consultant.

No responses yet

Write a response