😎

AbuseIPDBを使った一括ブラックリスト検索

2025/01/17に公開

はじめに

インターネットに公開しているWebアプリケーションを管理していると、不特定多数のIPアドレスからアクセスがありますが、その中には攻撃を目的としたアクセスもあります。
特にDDoS攻撃を受けたりすると、大量のアクセスログの解析が必要になりますが、その際どこからのアクセスなのかを分析することも多いです。
仕事上、IPアドレスの分析(ブラックリストに登録されているかなど)を確認する際に「AbuseIPDB」を使うことが多くなってきたので、調査手法を記事に残しておこうと思います。

本記事の目的

  1. AbuseIPDBについて知ってもらう
  2. 効率よく検索できるプログラムを作成したので、その紹介

AbuseIPDBとは

https://www.abuseipdb.com
AbuseIPDBは、不審なIPアドレスの情報を世間一般から広く情報収集し、ブラックリスト一覧として保有しているデータベースです(正確にはそれらを管理しているプロジェクト)。
情報を収集するだけではなく、ブラックリスト一覧として提供もしてくれています。
IPアドレスがブラックリストとして登録されているかだけではなく、「国」や「ISP」の情報、ブラックリストとしての"確らしさ"[1]の評価もしてくれます。

AbuseIPDBの公式サイトからだと、一つ一つIPアドレスを入力して確認することになりますが、調査する時は大抵、大量のIPアドレスを分析することになるので、手動で検索するのは現実的ではありません。
そんな場合、APIも用意されているため、それを利用するとCLIで検索することができます。

APIを使ったブラックリスト検索の方法

APIを使った検索を行う場合は、AbuseIPDBのアカウント作成が必要になります。今回は作成方法は割愛しますが、無償でも作成可能です。
ただし、無償の場合は、APIの実行回数に制限(1,000回/日)があります。詳細は、公式サイトを確認ください。
公式サイトのドキュメントでは、cURL、Python、PHP、C#、VBScriptを使った方法が記載されていますが、今回はPythonを使って検索するプログラムを作成してみます。

事前準備

以下を事前に準備しておきます。

  1. Pythonを実行できる環境
  2. requests ライブラリをインストール
  3. pandas ライブラリをインストール(後々jsonをcsvに変換しやすくするため)
  4. AbuseIPDBにログインしてAPIキーの払い出し
  5. IPアドレス一覧のファイル

ブラックリストの確認

公式サイトにAPIを実行するためのプログラム例は記載されているのですが、結局IPアドレスを1つずつしか検索できないので、複数IPアドレスを同時に検索できるようなプログラムを作成してみました。
以下は、環境に合わせて適宜修正してください。
 import_file:読み込むIPアドレス一覧のファイル
 Key:払い出したAPIキーの値

※動作保証はできませんので、利用する場合は自己責任で利用ください。

ip_list.txt
8.8.8.8
8.8.4.4
check_blackist.py
import requests
import json
import pandas as pd

# 検索したいIPアドレスの記載されたファイルを指定
import_file = 'ip_list.txt'

# Defining the api-endpoint
url = 'https://api.abuseipdb.com/api/v2/check'

# ファイルの読み込み
with open(import_file, 'r', encoding='utf-8') as f:
    lines = f.readlines()

# ファイルの行数を確認
count = sum([1 for _ in open(import_file)])

# 行数カウント用
i = 0

# 本処理
while i < count:
    querystring = {
        'ipAddress': lines[i].rstrip(),
        'maxAgeInDays': '90'
    }
    headers = {
        'Accept': 'application/json',
        'Key': '払い出したAPIキー'
    }

    response = requests.request(method='GET', url=url, headers=headers, params=querystring)

    # Formatted output
    decodedResponse = json.loads(response.text)
    print(json.dumps(decodedResponse, sort_keys=True, indent=4),end=',')

    i = i + 1

実行すると、以下のような結果が返ってきます。

response
{
    "data": {
        "abuseConfidenceScore": 0,
        "countryCode": "US",
        "domain": "google.com",
        "hostnames": [
            "dns.google"
        ],
        "ipAddress": "8.8.8.8",
        "ipVersion": 4,
        "isPublic": true,
        "isTor": false,
        "isWhitelisted": true,
        "isp": "Google LLC",
        "lastReportedAt": "2025-01-17T12:01:51+00:00",
        "numDistinctUsers": 33,
        "totalReports": 151,
        "usageType": "Content Delivery Network"
    }
},{
    "data": {
        "abuseConfidenceScore": 0,
        "countryCode": "US",
        "domain": "google.com",
        "hostnames": [
            "dns.google"
        ],
        "ipAddress": "8.8.4.4",
        "ipVersion": 4,
        "isPublic": true,
        "isTor": false,
        "isWhitelisted": true,
        "isp": "Google LLC",
        "lastReportedAt": "2025-01-15T16:00:52+00:00",
        "numDistinctUsers": 12,
        "totalReports": 37,
        "usageType": "Data Center/Web Hosting/Transit"
    }
},

abuseConfidenceScoreがブラックリストの確らしさ
countryCodeが国
になります。
このままだと出力がjsonになっていて視認性が悪かったので、csvに変換してから表形式で分析をしました。
csvに変換するスクリプトも作成しましたが、また機会があれば(要望があれば)紹介できればと思います。

まとめ

WAFなんかを入れていると自動判定してくれるので、あまり自ら分析する機会は多くないかもしれませんが、手動でログ分析する時には役立つかもしれないです。
また、プログラムは初心者なので、もっと効率的な方法があればぜひ教えてください!

脚注
  1. ここでいう「確らしさ」とは、「ブラックリストとして登録されているIPアドレスが本当に悪用されているものなのか」のことです。スコアが高いほど悪用されている可能性が高くなります。スコアは、「0 - 100」の間で評価されます。
    スコアがどのように算出されているかの明確な記載はありませんが、公式サイトのFAQに説明が記載されていますので、そちらも参考にしてみてください。
    11. What is the "Confidence of Abuse" rating? How is it calculated? ↩︎

Discussion