欺骗Wappalyzer插件指纹识别

语言: CN / TW / HK

你怎么知道Wappalyzer是不是在骗你?

Wappalyzer插件检测原理

插件是开源的 https://github.com/wappalyzer/wappalyzer

readme中提到会收集cookie,dom,js,css,header等数据,通过既定规则匹配,实现获取信息并匹配版本

其中js和dom比较特别,这里以js为例分析

https://github.com/wappalyzer/wappalyzer/blob/v6.10.18/src/drivers/webextension/js/content.js#L36-L42

function getJs(technologies) {
  return inject('js/js.js', 'js', {
    technologies: technologies
      .filter(({ js }) => Object.keys(js).length)
      .map(({ name, js }) => ({ name, chains: Object.keys(js) })),
  })
}

会插入一个 js/js.js 到前端去执行

https://github.com/wappalyzer/wappalyzer/blob/v6.10.18/src/drivers/webextension/js/js.js

代码比较长,简化代码逻辑如下

/* eslint-env browser */

;(function () {
  try {
    const onMessage = ({ data }) => {
      检查data是否是指纹规则

      removeEventListener('message', onMessage)

      postMessage({
        wappalyzer: {
          js: 执行指纹规则的结果
        },
      })
    }

    addEventListener('message', onMessage)
  } catch (e) {
    // Fail quietly
  }
})()

可以看到,这个js会启动监听message,插件后台会将指纹规则postMessage的方式传到前端,又前端进行指纹匹配,将结果用postMessage传回后台

伪造指纹

那么我们也可以手动postMessage一些数据去伪造指纹匹配结果

由于wappalyzer收到规则后会删除监听,可以hook removeEventListener 函数,在调用时就可以手动postMessage伪造指纹

// hook removeEventListener
let rel = removeEventListener;
removeEventListener = (name, func, opt) => {
  if (
    name === "message" &&
    func &&
    func.toString().includes("wappalyzer.technologies") !== -1 &&
    func.toString().includes("removeEventListener") !== -1 &&
    func.toString().includes("__UNDEFINED__") !== -1 &&
    func.toString().includes("postMessage") !== -1
  ) {
    poc();
    rel(name, func, opt);
  } else {
    rel(name, func, opt);
  }
};

const poc = () => {
  postMessage({
    wappalyzer: {
      js: [
        {
          name: "jQuery",
          chain: "$.fn.jquery",
          value: "99.99.99",
        },
      ],
    },
  });
};

同样的道理,把指纹库里的全部post过去就有全部指纹了