Wappalyzerによる判定方法とWordPressの判定パターンについて

日々の業務でWappalyzerを使っている方も多いのではないでしょうか。
私自身も、仕事等でウェブサイトの構築方法を確認するためにWappalyzerをよく活用しています。

しかし、たまにソースコードを見ても全くWordPressに見えないが…?というサイトがWappalyzerでWordPressと判定されているようなことも。
そうすると誤検知の可能性もある??とWappalyzerの技術判定のポイントが気になってくるもの。

今回調べてみたので、備忘録としてまとめます。

Wappalyzerによる判定方法

判定ロジックの記述箇所

Wappalyzerはオープンソースで提供されているため、コードの中身はGitHub上で閲覧可能です。

各技術への判定ロジックもこの中に記述されているため、本リポジトリに絞って「repo:dochne/wappalyzer {調べたい技術名}」と検索してみます。
例えば次のような感じ。

repo:dochne/wappalyzer wordpress

現時点だと「/src/technologies/●●●.json」というファイル名でヒットするものの中に判定ロジックのコードがありました。
WordPressだとこちら。
https://github.com/dochne/wappalyzer/blob/main/src/technologies/w.json

  "WordPress": {
    "cats": [
      1,
      11
    ],
    "cpe": "cpe:2.3:a:wordpress:wordpress:*:*:*:*:*:*:*:*",
    "description": "WordPress is a free and open-source content management system written in PHP and paired with a MySQL or MariaDB database. Features include a plugin architecture and a template system.",
    "headers": {
      "X-Pingback": "/xmlrpc\\.php$",
      "link": "rel=\"https://api\\.w\\.org/\""
    },
    "html": [
      "<link rel=[\"']stylesheet[\"'] [^>]+/wp-(?:content|includes)/",
      "<link[^>]+s\\d+\\.wp\\.com"
    ],
    "icon": "WordPress.svg",
    "implies": [
      "PHP",
      "MySQL"
    ],
    "js": {
      "wp_username": ""
    },
    "meta": {
      "generator": "^WordPress(?: ([\\d.]+))?\\;version:\\1",
      "shareaholic:wp_version": ""
    },
    "oss": true,
    "pricing": [
      "low",
      "recurring",
      "freemium"
    ],
    "saas": true,
    "scriptSrc": [
      "/wp-(?:content|includes)/",
      "wp-embed\\.min\\.js"
    ],
    "website": "https://wordpress.org"
  },

コードの読み方

リポジトリトップのSpecification(仕様)の「JSON fields」欄に、このコードの説明があります。
「JSON fields」欄は次のように分類できます。

  • Wappalyzer側で使う情報
    →「Required properties」、「Optional properties」、「Implies, requires and excludes (optional)
  • 判定ロジックに関係する情報
    →「Patterns (optional)

このPatternsに該当するプロパティを先ほどのWordPressコードから抜き出してみます。

"headers": {
  "X-Pingback": "/xmlrpc\\.php$",
  "link": "rel=\"https://api\\.w\\.org/\""
},
"html": [
  "<link rel=[\"']stylesheet[\"'] [^>]+/wp-(?:content|includes)/",
  "<link[^>]+s\\d+\\.wp\\.com"
],
"js": {
  "wp_username": ""
},
"meta": {
  "generator": "^WordPress(?: ([\\d.]+))?\\;version:\\1",
  "shareaholic:wp_version": ""
},
"scriptSrc": [
  "/wp-(?:content|includes)/",
  "wp-embed\\.min\\.js"
],

ここら辺は基本的にJavaScriptの正規表現で記述されてますが、こうして見てみると「WordPressサイトだとこういうコードよく見るな」とピンとくるものも多いですね。
例として、次のようなコードが上のWordPress判定にヒットします。

<meta name="generator" content="WordPress 6.6.2" />
<link rel='stylesheet' id='wp-block-navigation-css' href='https://example.com/wp-includes/blocks/navigation/style.min.css?ver=6.6.2' media='all' />

ちなみにjsは指定オブジェクトが存在するか否か、scriptSrcは読み込まれるJavaScriptファイルのURLにマッチするか否かの違い。
私がWordPressに見えないな~と思ったサイトの場合、レスポンスヘッダーのlinkがヒットしていました。

以上がWordPressの判定ロジックの中身でした。

Patternsには他にもdom(HTML要素のプロパティ、属性等から判定、dns(DNSレコードから判定)などのプロパティがあるようです。
詳しくはリポジトリの説明をご覧ください。

https://github.com/dochne/wappalyzer

まとめ

Wappalyzerはこんな要素まで拾って推測・判定しているんだという驚きと、各技術においてこういうところに固有の値を持っているんだな~という勉強になりました。

人気のツールだと思うので、使用技術を隠したい場合は”最低限ここを抑えるべき”という指標になりそうですね。

Wappalyzer を騙してみる