From 984eb4dad4fe4975ecb59eafffa6bd15222eb1da Mon Sep 17 00:00:00 2001 From: karasu Date: Tue, 9 Apr 2024 21:53:12 +0800 Subject: [PATCH] feat(route): hitcon (#15142) * feat(route): hitcon * type-only imports * Update lib/routes/hitcon/zeroday.ts Co-authored-by: Tony * Update lib/routes/hitcon/zeroday.ts Co-authored-by: Tony * Update lib/routes/hitcon/zeroday.ts Co-authored-by: Tony * add art-template and pubDate * fix: define __dirname --------- --- lib/routes/hitcon/namespace.ts | 6 ++ lib/routes/hitcon/templates/zeroday.art | 8 ++ lib/routes/hitcon/zeroday.ts | 109 ++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 lib/routes/hitcon/namespace.ts create mode 100644 lib/routes/hitcon/templates/zeroday.art create mode 100644 lib/routes/hitcon/zeroday.ts diff --git a/lib/routes/hitcon/namespace.ts b/lib/routes/hitcon/namespace.ts new file mode 100644 index 000000000..3cda88d4c --- /dev/null +++ b/lib/routes/hitcon/namespace.ts @@ -0,0 +1,6 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'HITCON', + url: 'hitcon.org', +}; diff --git a/lib/routes/hitcon/templates/zeroday.art b/lib/routes/hitcon/templates/zeroday.art new file mode 100644 index 000000000..f051ea4fa --- /dev/null +++ b/lib/routes/hitcon/templates/zeroday.art @@ -0,0 +1,8 @@ +
    +
  • {{ vender }}
  • +
  • ZDID: {{ code }}
  • +
  • 風險: {{ risk }}
  • +
  • 處理狀態: {{ status }}
  • +
  • 通報者: {{ reporter }}
  • +
  • 通報日期: {{ date }}
  • +
diff --git a/lib/routes/hitcon/zeroday.ts b/lib/routes/hitcon/zeroday.ts new file mode 100644 index 000000000..ce3aa2a29 --- /dev/null +++ b/lib/routes/hitcon/zeroday.ts @@ -0,0 +1,109 @@ +import type { Data, DataItem, Route } from '@/types'; +import type { Context } from 'hono'; +import { load } from 'cheerio'; +import puppeteer from '@/utils/puppeteer'; +import logger from '@/utils/logger'; +import { art } from '@/utils/render'; +import path from 'node:path'; +import { parseDate } from '@/utils/parse-date'; +import { getCurrentPath } from '@/utils/helpers'; + +const __dirname = getCurrentPath(import.meta.url); + +export const route: Route = { + name: '漏洞', + categories: ['programming'], + path: '/zeroday/vulnerability/:status?', + example: '/hitcon/zeroday/vulnerability', + parameters: { + status: '漏洞状态,见下表', + }, + maintainers: ['KarasuShin'], + radar: [ + { + source: ['zeroday.hitcon.org/vulnerability/:status?'], + }, + ], + features: { + requirePuppeteer: true, + }, + handler, + description: `| 缺省 | all | closed | disclosed | patching | + | ------ | ---- | ------ | --------- | -------- | + | 活動中 | 全部 | 關閉 | 公開 | 修補中 |`, +}; + +const baseUrl = 'https://zeroday.hitcon.org/vulnerability'; + +const titleMap = { + all: '全部', + closed: '關閉', + disclosed: '公開', + patching: '修補中', +}; + +async function handler(ctx: Context): Promise { + let url = baseUrl; + const status = ctx.req.param('status'); + if (status) { + url += `/${status}`; + } + + const browser = await puppeteer(); + const page = await browser.newPage(); + await page.setRequestInterception(true); + + page.on('request', (request) => { + request.resourceType() === 'document' ? request.continue() : request.abort(); + }); + + logger.http(`Requesting ${url}`); + await page.goto(url, { + waitUntil: 'domcontentloaded', + }); + + const response = await page.evaluate(() => document.documentElement.innerHTML); + browser.close(); + + const $ = load(response); + const items: DataItem[] = $('.zdui-strip-list>li') + .toArray() + .map((el) => { + const title = $(el).find('.title a'); + const vulData = $(el).find('.vul-data'); + const code = vulData + .find('.code') + .contents() + .filter(function () { + return this.nodeType === 3; + }) + .text(); + const risk = vulData.find('.risk span').eq(1).text(); + const vender = vulData.find('.vender').find('.v-name-full').text(); + const status = vulData.find('.status').text().replace('Status:', '').trim(); + const date = vulData.find('.date').text().replace('Date:', '').trim(); + const reporter = vulData.find('.zdui-author-badge').find('a>span').text(); + const description = art(path.join(__dirname, 'templates/zeroday.art'), { + code, + risk, + vender, + status, + date, + reporter, + }); + + return { + title: title.text(), + link: title.attr('href'), + description, + pubDate: parseDate(date), + }; + }); + + return { + title: status ? titleMap[status] ?? 'ZeroDay' : '活動中', + link: url, + item: items, + image: 'https://zeroday.hitcon.org/images/favicon/favicon.png', + }; +}