给你的网站集成谷歌安全浏览(Google Safe Browsing)服务

小助手读文章 00:00 / 00:00

温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。

安全浏览(Safe Browsing)是 Google 的安全团队打造的一项服务,旨在发现网上的不安全网站并将潜在危害告知用户和网站站长,具体介绍可以参考官方网页。简单来说就是 Google 的安全浏览服务会检查数十亿个网址以及相应网页中的软件和内容,发现其中包含病毒、网站被篡改等不安全问题,并在用户访问时发出警告,这是一项很有用的服务,故考虑将其集成到网站外链处理中,当用户点击外链时实时进行检测提醒。

集成使用安全浏览服务可以有两种方式,一种是直接抓取安全浏览检测网页的内容,判断返回的状态:

000.安全检测.png

这种方法可以实现目标,但效率一般,不在本文探讨中;另一种方法是使用 Google 提供的 Safe Browsing API,这种方法相比前一种更为高效,故我们接下来一起来看看如何利用 API 的方式来集成安全浏览服务。

注意,不管是哪种方法,都要求运行此服务的主机能够访问 Google 网站。

注册

注册账号

使用 Safe Browsing API 要求必须要有谷歌(Google)账号,因此在进行下一步前请先注册账号,可以使用自己的邮箱注册,这里就不详细介绍,按页面提示操作即可:

001.注册账号.png

注册 API

打开 Google Developers Console API 库,从项目下拉列表中,选择一个项目或创建一个新项目,由于现在 API 已经集成到 Google Cloud Platform,创建项目前可能需要先绑定有效的付款方式(API 不收费):

002.选择项目.png

在 Google API 标签中,搜索并选择 Safe Browsing API ,注意有两个 API,我们选择新版 v4 的:

003.搜索 API.png

然后单击启用 API:

004.启用 API.png

接下来,我们启用凭据:

005.创建凭据.png

选择安全浏览 Safe Browsing API,创建:

006.创建凭据.png

凭据已创建,记下来备用:

007.复制凭据.png

为保证凭据安全,建议进行使用限制,比如来源页、允许 IP 等:

008.设置限制.png

到这里 API 凭据 KEY 已经成功获取。

使用

CURL 及参数解析

获得 KEY 后我们可以先测试一下效果:

$ curl -X POST \
  'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=YOUR_KEY_HERE' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '  {
    "client": {
      "clientId":      "vcloud",
      "clientVersion": "1.1.1"
    },
    "threatInfo": {
      "threatTypes":      ["MALWARE", "SOCIAL_ENGINEERING"],
      "platformTypes":    ["WINDOWS"],
      "threatEntryTypes": ["URL"],
      "threatEntries": [
        {"url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"},
        {"url": "http://stackoverflow.com/"}
      ]
    }
  }'

得到了如下响应:

{
    "matches": [
        {
            "threatType": "SOCIAL_ENGINEERING",
            "platformType": "WINDOWS",
            "threat": {
                "url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"
            },
            "cacheDuration": "300s",
            "threatEntryType": "URL"
        }
    ]
}

我们提交了两条 URL 检测,但只回复了一条,说明如果网址是安全的,那么回复的内容为空,后续我们就可以以此来判断是否安全。

我们看一下请求的 JSON 参数:

{
    "client": {
      "clientId":      "vcloud",
      "clientVersion": "1.1.1"
    },
    "threatInfo": {
      "threatTypes":      ["MALWARE", "SOCIAL_ENGINEERING"],
      "platformTypes":    ["WINDOWS"],
      "threatEntryTypes": ["URL"],
      "threatEntries": [
        {"url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"},
        {"url": "http://stackoverflow.com/"}
      ]
    }
  }

client 表示与安全浏览 API 请求关联的客户端元数据,可以根据自己需求实际设置:

clientId 表示使用 Safe Browsing API 的客户端唯一标识 ID,clientVersion 表示客户端版本。

threatInfo 表示要进行安全检测匹配的内容:


threatTypes:安全问题类型,主要有:

THREAT_TYPE_UNSPECIFIED未知的威胁类型
MALWARE恶意软件威胁类型
SOCIAL_ENGINEERING社会工程威胁类型
UNWANTED_SOFTWARE不需要的软件威胁类型
POTENTIALLY_HARMFUL_APPLICATION潜在有害的应用程序威胁类型

这也印证刚说的,如果检测是安全的,不会直接返回安全,而是不回复任何内容,凡有回复内容皆是存在安全风险。


platformTypes:安全问题平台,主要有:

PLATFORM_TYPE_UNSPECIFIED未知的平台
WINDOWS对 Windows 构成威胁
LINUX对 Linux 构成威胁
ANDROID对 Android 构成威胁
OSX对 OS X 构成威胁
IOS对 iOS 构成了威胁
ANY_PLATFORM对至少一个已定义的平台构成威胁
ALL_PLATFORMS对所有已定义的平台构成威胁
CHROME对 Chrome 构成威胁


threatEntryType:构成威胁的类型,区别于 threatTypes 和 platformTypes,一次只能指定一个:

THREAT_ENTRY_TYPE_UNSPECIFIED未指定
URL一个URL
EXECUTABLE可执行程序


threatEntries(threatEntry):需要检测的目标,可以是 URL,也可以是哈希值,但一个JSON 中只能有一个(可以有多个 JSON):

hash二进制格式,对于 JSON 请求,哈希值由 base64 编码
url完整的 URL(无需编码)
digest二进制或十六进制,针对可执行文件,对于 JSON 请求,哈希值由 base64 编码

再来看一下回复的 ThreatMatch JSON 参数:

{
    "matches": [
        {
            "threatType": "SOCIAL_ENGINEERING",
            "platformType": "WINDOWS",
            "threat": {
                "url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"
            },
            "cacheDuration": "300s",
            "threatEntryType": "URL"
        }
    ]
}

其中 threatTypeplatformType 在请求 JSON 已经讲过了;threat 表示匹配到的请求 JSON 中的 threatEntries 中的有安全风险的条目;cacheDuration 表示该匹配的缓存生存期,客户端若有缓存安全警报,则缓存时间不应超过此时间以避免误报;threatEntryType 则表示检测的 threat 的类型。

之所以将 JSON 参数讲解这么详细,是因为我们可以根据需要指定检测特定的安全类型、平台、URL 等等,以提高效率。

Python 示例

import requests
url = "https://safebrowsing.googleapis.com/v4/threatMatches:find"
querystring = {"key":"YOUR_KEY"}
payload = """
  {
    "client": {
      "clientId":      "yourcompanyname",
      "clientVersion": "1.5.2"
    },
    "threatInfo": {
      "threatTypes":      ["MALWARE", "SOCIAL_ENGINEERING"],
      "platformTypes":    ["WINDOWS"],
      "threatEntryTypes": ["URL"],
      "threatEntries": [
        {"url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"},
        {"url": "http://stackoverflow.com/"}
      ]
    }
  }

"""
headers = {
    'content-type': "application/json",
    'cache-control': "no-cache",
    'postman-token': "460d6d44-4a55-d6ab-fb58-2ff9fb306154"
    }
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)

PHP 示例

<?php
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://safebrowsing.googleapis.com/v4/threatMatches:find?key=YOUR_KEY",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "  {
"client": {
  "clientId":      "yourcompanyname",
  "clientVersion": "1.5.2"
},
"threatInfo": {
  "threatTypes":      ["MALWARE", "SOCIAL_ENGINEERING"],
  "platformTypes":    ["WINDOWS"],
  "threatEntryTypes": ["URL"],
  "threatEntries": [
    {"url": "https://accounts-wallets.redirectme.net/webapps/57a39/websrc"},
    {"url": "http://stackoverflow.com/"}
  ]
}
  }",
  CURLOPT_HTTPHEADER => array(
    "cache-control: no-cache",
    "content-type: application/json",
    "postman-token: b05b8d34-85f2-49cf-0f8e-03686a71e4e9"
  ),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
?>

Typecho

参照本站代码:

function.php(供参考,不要直接照抄):

......
function safeCheck($url){
        if(!isset($url) || empty($url)){
                return 'ERROR: URL is required.';
        }
        if(!isset(Helper::options()->safeapi) || empty(Helper::options()->safeapi)){
                return 'ERROR: API Key is required.';
        } else {
                $apiKey = Helper::options()->safeapi;
        }
        if(!isset($_SERVER['HTTP_USER_AGENT']) || empty($_SERVER['HTTP_USER_AGENT'])){
                return 'ERROR: Unknown platform.';
        } else {
                $os = getOS($_SERVER['HTTP_USER_AGENT'], 1);
                if(strpos($os,'Windows') === true) {
                        $platform = 'WINDOWS';
                } elseif(strpos($os,'Linux') === true) {
                        $platform = 'LINUX';
                } elseif(strpos($os,'Android') === true) {
                        $platform = 'ANDROID';
                } else {
                        $platform = 'IOS';
                }
        }
        $apiUrl = 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key='.$apiKey;
        $params = [
                'client' => [
                        'clientId' => 'armxmod',
                        'clientVersion' => '7.2.0'
                ],
                'threatInfo' => [
                        'threatTypes' =>['MALWARE', 'SOCIAL_ENGINEERING'],
                        'platformTypes' => $platform,
                        'threatEntryTypes' => ['URL'],
                        'threatEntries' => [
                                [ 'url' => $url ]
                        ]
                ]
        ];
        $curl = curl_init($apiUrl);
        curl_setopt_array($curl, array(
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 3,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => json_encode($params),
                CURLOPT_HTTPHEADER => array(
                        'cache-control: no-cache',
                        'content-type: application/json'
                ),
        ));
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        if ($err) {
                return 'ERROR: ' . $err;
        } else {
                $res = json_decode($response,true);
                if ($res['error']['message']){
                    return $res['error']['message'];
                } else if($res['matches']['threatType']){
                    return $res['matches']['threatType'];
                } else {
                    return 'safe';
                }
        }
}
......

在需要检测的地方,使用如下代码即可:

......
<?php echo '安全检测结果:'.safeCheck($url);?>
......

注意

Safe Broswing API 是有调用限制的,所以要注意 KEY 的调用限制:

Requests per day(每天):10,000 次
Requests per 100 seconds per user(100 秒内):3,000 次

另外,API KEY 似乎只有 24 小时有效期(测试中出现了 API key expired. Please renew the API key 错误),暂时没看到哪里可以设置永久的,知道的朋友可以告知一下,感谢。


参考文章:

1、《官方 API 说明:Safe Browsing API
2、《PHP check website url using safe browsing API


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 Googlephp教程typechowordpress安全浏览safe broswing 的文章

 本文最后更新于 2019/06/05 17:00:00,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > 运维 > 给你的网站集成谷歌安全浏览(Google Safe Browsing)服务

精选评论

  1. chancat
    chancat 回复

    Windows 10Chrome 80.0.3987.149来自 江苏 的大神

    谢谢分享

  2. Slblog
    Slblog 回复

    Ubuntu LinuxFirefox 67.0来自 湖北 的大神

    看了一下,还挺好用的,不过都是PHP代码格式的,而我是Hexo的

    1. 欧文斯

      大致方法思路是类似的 icon_mrgreen.gif

  3. 提莫酱
    提莫酱 回复

    LinuxChrome 85.0.4183.102来自 河南 的大神

    被注册API难住了。。

    1. 欧文斯

      难道又改版了?GCP 后台经常改,入口名字可能不太一样,但总体上还是差不多的

      1. 提莫将
        提莫将 回复

        LinuxFirefox 60.0来自 河南 的大神

        不是,没信用卡惹 icon_mrgreen.gif

        1. 欧文斯

          icon_razz.gif GCP 也挺香,申请一张招行卡没太大难度