@panguard-ai/threat-cloud 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit-logger.d.ts +46 -0
- package/dist/audit-logger.d.ts.map +1 -0
- package/dist/audit-logger.js +105 -0
- package/dist/audit-logger.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +115 -0
- package/dist/cli.js.map +1 -0
- package/dist/correlation-engine.d.ts +41 -0
- package/dist/correlation-engine.d.ts.map +1 -0
- package/dist/correlation-engine.js +313 -0
- package/dist/correlation-engine.js.map +1 -0
- package/dist/database.d.ts +63 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +444 -0
- package/dist/database.js.map +1 -0
- package/dist/feed-distributor.d.ts +36 -0
- package/dist/feed-distributor.d.ts.map +1 -0
- package/dist/feed-distributor.js +125 -0
- package/dist/feed-distributor.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/ioc-store.d.ts +83 -0
- package/dist/ioc-store.d.ts.map +1 -0
- package/dist/ioc-store.js +278 -0
- package/dist/ioc-store.js.map +1 -0
- package/dist/query-handlers.d.ts +40 -0
- package/dist/query-handlers.d.ts.map +1 -0
- package/dist/query-handlers.js +211 -0
- package/dist/query-handlers.js.map +1 -0
- package/dist/reputation-engine.d.ts +44 -0
- package/dist/reputation-engine.d.ts.map +1 -0
- package/dist/reputation-engine.js +169 -0
- package/dist/reputation-engine.js.map +1 -0
- package/dist/rule-generator.d.ts +47 -0
- package/dist/rule-generator.d.ts.map +1 -0
- package/dist/rule-generator.js +238 -0
- package/dist/rule-generator.js.map +1 -0
- package/dist/scheduler.d.ts +52 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +143 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server.d.ts +99 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +809 -0
- package/dist/server.js.map +1 -0
- package/dist/sighting-store.d.ts +61 -0
- package/dist/sighting-store.d.ts.map +1 -0
- package/dist/sighting-store.js +191 -0
- package/dist/sighting-store.js.map +1 -0
- package/dist/types.d.ts +352 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feed Distributor
|
|
3
|
+
* 情報分發模組
|
|
4
|
+
*
|
|
5
|
+
* Generates blocklists, IoC feeds, and agent update packages.
|
|
6
|
+
*
|
|
7
|
+
* @module @panguard-ai/threat-cloud/feed-distributor
|
|
8
|
+
*/
|
|
9
|
+
export class FeedDistributor {
|
|
10
|
+
db;
|
|
11
|
+
constructor(db) {
|
|
12
|
+
this.db = db;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate IP blocklist as plain text (one IP per line).
|
|
16
|
+
* Only includes redistributable IoCs to comply with feed licenses.
|
|
17
|
+
* 產生 IP 封鎖清單(僅包含可轉散佈的 IoC,遵守授權)
|
|
18
|
+
*/
|
|
19
|
+
getIPBlocklist(minReputation = 70) {
|
|
20
|
+
const rows = this.db
|
|
21
|
+
.prepare(`SELECT normalized_value
|
|
22
|
+
FROM iocs
|
|
23
|
+
WHERE type = 'ip' AND status = 'active' AND reputation_score >= ?
|
|
24
|
+
AND (json_extract(metadata, '$.redistributable') != 'false'
|
|
25
|
+
OR json_extract(metadata, '$.redistributable') IS NULL
|
|
26
|
+
OR source NOT LIKE 'feed:%')
|
|
27
|
+
ORDER BY reputation_score DESC`)
|
|
28
|
+
.all(minReputation);
|
|
29
|
+
return rows.map((r) => r.normalized_value).join('\n');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate domain blocklist as plain text.
|
|
33
|
+
* 產生 Domain 封鎖清單
|
|
34
|
+
*/
|
|
35
|
+
getDomainBlocklist(minReputation = 70) {
|
|
36
|
+
const rows = this.db
|
|
37
|
+
.prepare(`SELECT normalized_value
|
|
38
|
+
FROM iocs
|
|
39
|
+
WHERE type = 'domain' AND status = 'active' AND reputation_score >= ?
|
|
40
|
+
AND (json_extract(metadata, '$.redistributable') != 'false'
|
|
41
|
+
OR json_extract(metadata, '$.redistributable') IS NULL
|
|
42
|
+
OR source NOT LIKE 'feed:%')
|
|
43
|
+
ORDER BY reputation_score DESC`)
|
|
44
|
+
.all(minReputation);
|
|
45
|
+
return rows.map((r) => r.normalized_value).join('\n');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate JSON IoC feed.
|
|
49
|
+
* 產生 JSON IoC feed
|
|
50
|
+
*/
|
|
51
|
+
getIoCFeed(minReputation = 50, limit = 1000, since) {
|
|
52
|
+
const conditions = ["status = 'active'", 'reputation_score >= ?'];
|
|
53
|
+
const params = [minReputation];
|
|
54
|
+
if (since) {
|
|
55
|
+
conditions.push('last_seen > ?');
|
|
56
|
+
params.push(since);
|
|
57
|
+
}
|
|
58
|
+
const safeLimit = Math.min(Math.max(1, limit), 10000);
|
|
59
|
+
const where = conditions.join(' AND ');
|
|
60
|
+
const rows = this.db
|
|
61
|
+
.prepare(`SELECT type, normalized_value, threat_type, reputation_score, confidence, last_seen, tags
|
|
62
|
+
FROM iocs
|
|
63
|
+
WHERE ${where}
|
|
64
|
+
ORDER BY reputation_score DESC
|
|
65
|
+
LIMIT ?`)
|
|
66
|
+
.all(...params, safeLimit);
|
|
67
|
+
const entries = rows.map((r) => ({
|
|
68
|
+
type: r.type,
|
|
69
|
+
value: r.normalized_value,
|
|
70
|
+
threatType: r.threat_type,
|
|
71
|
+
reputation: r.reputation_score,
|
|
72
|
+
confidence: r.confidence,
|
|
73
|
+
lastSeen: r.last_seen,
|
|
74
|
+
tags: JSON.parse(r.tags),
|
|
75
|
+
}));
|
|
76
|
+
return {
|
|
77
|
+
generatedAt: new Date().toISOString(),
|
|
78
|
+
totalEntries: entries.length,
|
|
79
|
+
entries,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Generate agent update package (rules + IoCs since a given timestamp).
|
|
84
|
+
* 產生 Agent 更新包
|
|
85
|
+
*/
|
|
86
|
+
getAgentUpdate(since) {
|
|
87
|
+
const sinceDate = since ?? new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
|
|
88
|
+
// Fetch new rules
|
|
89
|
+
const rules = this.db
|
|
90
|
+
.prepare(`SELECT rule_id as ruleId, rule_content as ruleContent, published_at as publishedAt, source
|
|
91
|
+
FROM rules
|
|
92
|
+
WHERE published_at > ?
|
|
93
|
+
ORDER BY published_at ASC`)
|
|
94
|
+
.all(sinceDate);
|
|
95
|
+
// Fetch high-reputation IoCs updated since
|
|
96
|
+
const iocRows = this.db
|
|
97
|
+
.prepare(`SELECT type, normalized_value, threat_type, reputation_score, confidence, last_seen, tags
|
|
98
|
+
FROM iocs
|
|
99
|
+
WHERE status = 'active' AND reputation_score >= 60 AND updated_at > ?
|
|
100
|
+
ORDER BY reputation_score DESC
|
|
101
|
+
LIMIT 500`)
|
|
102
|
+
.all(sinceDate);
|
|
103
|
+
const iocs = iocRows.map((r) => ({
|
|
104
|
+
type: r.type,
|
|
105
|
+
value: r.normalized_value,
|
|
106
|
+
threatType: r.threat_type,
|
|
107
|
+
reputation: r.reputation_score,
|
|
108
|
+
confidence: r.confidence,
|
|
109
|
+
lastSeen: r.last_seen,
|
|
110
|
+
tags: JSON.parse(r.tags),
|
|
111
|
+
}));
|
|
112
|
+
const totalActiveIoCs = this.db.prepare("SELECT COUNT(*) as count FROM iocs WHERE status = 'active'").get().count;
|
|
113
|
+
return {
|
|
114
|
+
generatedAt: new Date().toISOString(),
|
|
115
|
+
rules,
|
|
116
|
+
iocs,
|
|
117
|
+
stats: {
|
|
118
|
+
newRules: rules.length,
|
|
119
|
+
newIoCs: iocs.length,
|
|
120
|
+
totalActiveIoCs,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=feed-distributor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-distributor.js","sourceRoot":"","sources":["../src/feed-distributor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { ThreatCloudServer } from './server.js';
|
|
2
|
+
export { ThreatCloudDB } from './database.js';
|
|
3
|
+
export { IoCStore } from './ioc-store.js';
|
|
4
|
+
export { ReputationEngine } from './reputation-engine.js';
|
|
5
|
+
export { CorrelationEngine } from './correlation-engine.js';
|
|
6
|
+
export { RuleGenerator } from './rule-generator.js';
|
|
7
|
+
export { QueryHandlers } from './query-handlers.js';
|
|
8
|
+
export { FeedDistributor } from './feed-distributor.js';
|
|
9
|
+
export { SightingStore } from './sighting-store.js';
|
|
10
|
+
export { AuditLogger } from './audit-logger.js';
|
|
11
|
+
export { Scheduler } from './scheduler.js';
|
|
12
|
+
export type { AnonymizedThreatData, ThreatCloudRule, ThreatStats, ServerConfig, ApiResponse, IoCType, IoCStatus, IoCRecord, IoCInput, IoCLookupResult, TrapIntelligencePayload, EnrichedThreatEvent, PaginationParams, PaginatedResponse, ReputationConfig, CorrelationConfig, Campaign, CampaignScanResult, CampaignStats, DetectedPattern, RuleGenerationResult, RuleGeneratorConfig, TimeSeriesPoint, GeoDistributionEntry, TrendEntry, MitreHeatmapEntry, EnhancedStats, IoCFeedEntry, IoCFeedResponse, AgentUpdatePackage, SchedulerConfig, SourceReliability, SightingType, SightingInput, SightingRecord, AuditAction, AuditLogEntry, AuditLogQuery, FeedLicense, FeedSourceConfig, } from './types.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,EACX,OAAO,EACP,SAAS,EACT,SAAS,EACT,QAAQ,EACR,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { ThreatCloudServer } from './server.js';
|
|
2
|
+
export { ThreatCloudDB } from './database.js';
|
|
3
|
+
export { IoCStore } from './ioc-store.js';
|
|
4
|
+
export { ReputationEngine } from './reputation-engine.js';
|
|
5
|
+
export { CorrelationEngine } from './correlation-engine.js';
|
|
6
|
+
export { RuleGenerator } from './rule-generator.js';
|
|
7
|
+
export { QueryHandlers } from './query-handlers.js';
|
|
8
|
+
export { FeedDistributor } from './feed-distributor.js';
|
|
9
|
+
export { SightingStore } from './sighting-store.js';
|
|
10
|
+
export { AuditLogger } from './audit-logger.js';
|
|
11
|
+
export { Scheduler } from './scheduler.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IoC (Indicator of Compromise) Store
|
|
3
|
+
* IoC(入侵指標)儲存模組
|
|
4
|
+
*
|
|
5
|
+
* Handles CRUD, normalization, deduplication, and sighting-merge for IoCs.
|
|
6
|
+
*
|
|
7
|
+
* @module @panguard-ai/threat-cloud/ioc-store
|
|
8
|
+
*/
|
|
9
|
+
import type Database from 'better-sqlite3';
|
|
10
|
+
import type { IoCType, IoCStatus, IoCRecord, IoCInput, IoCLookupResult, PaginationParams, PaginatedResponse } from './types.js';
|
|
11
|
+
export declare class IoCStore {
|
|
12
|
+
private readonly db;
|
|
13
|
+
constructor(db: Database.Database);
|
|
14
|
+
/**
|
|
15
|
+
* Normalize IoC value for deduplication.
|
|
16
|
+
* 正規化 IoC 值以便去重
|
|
17
|
+
*/
|
|
18
|
+
normalizeValue(type: IoCType, value: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Auto-detect IoC type from value / 自動偵測 IoC 類型
|
|
21
|
+
*/
|
|
22
|
+
detectType(value: string): IoCType;
|
|
23
|
+
/**
|
|
24
|
+
* Upsert an IoC: insert if new, merge sighting if existing.
|
|
25
|
+
* Upsert IoC:新建或合併觀測
|
|
26
|
+
*/
|
|
27
|
+
upsertIoC(input: IoCInput): IoCRecord;
|
|
28
|
+
/**
|
|
29
|
+
* Lookup a single IoC by type+value / 以 type+value 查詢單一 IoC
|
|
30
|
+
*/
|
|
31
|
+
lookupIoC(type: IoCType, value: string): IoCRecord | null;
|
|
32
|
+
/**
|
|
33
|
+
* Lookup IoC with related threat count / 查詢 IoC 含相關威脅數
|
|
34
|
+
*/
|
|
35
|
+
lookupIoCWithContext(type: IoCType, value: string, countThreats: (ip: string) => number): IoCLookupResult;
|
|
36
|
+
/**
|
|
37
|
+
* Get IoC by ID / 以 ID 取得 IoC
|
|
38
|
+
*/
|
|
39
|
+
getIoCById(id: number): IoCRecord | null;
|
|
40
|
+
/**
|
|
41
|
+
* Get active IoCs by type with minimum reputation / 取得特定類型的活躍 IoC
|
|
42
|
+
*/
|
|
43
|
+
getActiveIoCsByType(type: IoCType, minReputation: number, limit: number): IoCRecord[];
|
|
44
|
+
/**
|
|
45
|
+
* Search IoCs with filters and pagination / 以篩選條件搜尋 IoC
|
|
46
|
+
*/
|
|
47
|
+
searchIoCs(filters: {
|
|
48
|
+
type?: IoCType;
|
|
49
|
+
source?: string;
|
|
50
|
+
minReputation?: number;
|
|
51
|
+
status?: IoCStatus;
|
|
52
|
+
since?: string;
|
|
53
|
+
search?: string;
|
|
54
|
+
}, pagination: PaginationParams): PaginatedResponse<IoCRecord>;
|
|
55
|
+
/**
|
|
56
|
+
* Batch update reputation scores / 批次更新信譽分數
|
|
57
|
+
*/
|
|
58
|
+
batchUpdateReputation(updates: Array<{
|
|
59
|
+
id: number;
|
|
60
|
+
reputationScore: number;
|
|
61
|
+
}>): void;
|
|
62
|
+
/**
|
|
63
|
+
* Expire stale IoCs / 過期未活躍的 IoC
|
|
64
|
+
*/
|
|
65
|
+
expireStaleIoCs(olderThan: string): number;
|
|
66
|
+
/**
|
|
67
|
+
* Delete expired IoCs beyond retention / 刪除超齡的已過期 IoC
|
|
68
|
+
*/
|
|
69
|
+
purgeExpiredIoCs(olderThan: string): number;
|
|
70
|
+
/**
|
|
71
|
+
* Get IoC counts by type / 取得各類型 IoC 數量
|
|
72
|
+
*/
|
|
73
|
+
getIoCCountsByType(): Record<string, number>;
|
|
74
|
+
/**
|
|
75
|
+
* Get top malicious IoCs / 取得最高威脅度 IoC
|
|
76
|
+
*/
|
|
77
|
+
getTopMaliciousIoCs(limit: number): IoCRecord[];
|
|
78
|
+
/**
|
|
79
|
+
* Get total active IoC count / 取得活躍 IoC 總數
|
|
80
|
+
*/
|
|
81
|
+
getTotalActiveCount(): number;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=ioc-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ioc-store.d.ts","sourceRoot":"","sources":["../src/ioc-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AA4CpB,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAMlD;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAuBpD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAsBlC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS;IA0DrC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAQzD;;OAEG;IACH,oBAAoB,CAClB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GACnC,eAAe;IASlB;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKxC;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAYrF;;OAEG;IACH,UAAU,CACR,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EACD,UAAU,EAAE,gBAAgB,GAC3B,iBAAiB,CAAC,SAAS,CAAC;IAuD/B;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAYpF;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAS1C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAO3C;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAW5C;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAO/C;;OAEG;IACH,mBAAmB,IAAI,MAAM;CAO9B"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IoC (Indicator of Compromise) Store
|
|
3
|
+
* IoC(入侵指標)儲存模組
|
|
4
|
+
*
|
|
5
|
+
* Handles CRUD, normalization, deduplication, and sighting-merge for IoCs.
|
|
6
|
+
*
|
|
7
|
+
* @module @panguard-ai/threat-cloud/ioc-store
|
|
8
|
+
*/
|
|
9
|
+
/** Convert DB row to IoCRecord / 將 DB 列轉換為 IoCRecord */
|
|
10
|
+
function rowToRecord(row) {
|
|
11
|
+
return {
|
|
12
|
+
id: row.id,
|
|
13
|
+
type: row.type,
|
|
14
|
+
value: row.value,
|
|
15
|
+
normalizedValue: row.normalized_value,
|
|
16
|
+
threatType: row.threat_type,
|
|
17
|
+
source: row.source,
|
|
18
|
+
confidence: row.confidence,
|
|
19
|
+
reputationScore: row.reputation_score,
|
|
20
|
+
firstSeen: row.first_seen,
|
|
21
|
+
lastSeen: row.last_seen,
|
|
22
|
+
sightings: row.sightings,
|
|
23
|
+
status: row.status,
|
|
24
|
+
tags: JSON.parse(row.tags),
|
|
25
|
+
metadata: JSON.parse(row.metadata),
|
|
26
|
+
createdAt: row.created_at,
|
|
27
|
+
updatedAt: row.updated_at,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export class IoCStore {
|
|
31
|
+
db;
|
|
32
|
+
constructor(db) {
|
|
33
|
+
this.db = db;
|
|
34
|
+
}
|
|
35
|
+
// -------------------------------------------------------------------------
|
|
36
|
+
// Normalization / 正規化
|
|
37
|
+
// -------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* Normalize IoC value for deduplication.
|
|
40
|
+
* 正規化 IoC 值以便去重
|
|
41
|
+
*/
|
|
42
|
+
normalizeValue(type, value) {
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
switch (type) {
|
|
45
|
+
case 'ip': {
|
|
46
|
+
// Strip port if present (e.g., "1.2.3.4:8080" -> "1.2.3.4")
|
|
47
|
+
const noPort = trimmed.replace(/:\d+$/, '');
|
|
48
|
+
return noPort.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
case 'domain':
|
|
51
|
+
// Lowercase, remove trailing dot
|
|
52
|
+
return trimmed.toLowerCase().replace(/\.$/, '');
|
|
53
|
+
case 'url':
|
|
54
|
+
// Lowercase scheme+host, strip trailing slash
|
|
55
|
+
return trimmed.toLowerCase().replace(/\/+$/, '');
|
|
56
|
+
case 'hash_md5':
|
|
57
|
+
case 'hash_sha1':
|
|
58
|
+
case 'hash_sha256':
|
|
59
|
+
return trimmed.toLowerCase();
|
|
60
|
+
default:
|
|
61
|
+
return trimmed.toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Auto-detect IoC type from value / 自動偵測 IoC 類型
|
|
66
|
+
*/
|
|
67
|
+
detectType(value) {
|
|
68
|
+
const v = value.trim();
|
|
69
|
+
// IPv4
|
|
70
|
+
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$/.test(v))
|
|
71
|
+
return 'ip';
|
|
72
|
+
// IPv6
|
|
73
|
+
if (v.includes(':') && /^[0-9a-fA-F:]+$/.test(v))
|
|
74
|
+
return 'ip';
|
|
75
|
+
// URL
|
|
76
|
+
if (/^https?:\/\//i.test(v))
|
|
77
|
+
return 'url';
|
|
78
|
+
// SHA-256
|
|
79
|
+
if (/^[a-fA-F0-9]{64}$/.test(v))
|
|
80
|
+
return 'hash_sha256';
|
|
81
|
+
// SHA-1
|
|
82
|
+
if (/^[a-fA-F0-9]{40}$/.test(v))
|
|
83
|
+
return 'hash_sha1';
|
|
84
|
+
// MD5
|
|
85
|
+
if (/^[a-fA-F0-9]{32}$/.test(v))
|
|
86
|
+
return 'hash_md5';
|
|
87
|
+
// Default to domain
|
|
88
|
+
return 'domain';
|
|
89
|
+
}
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
// CRUD / 資料操作
|
|
92
|
+
// -------------------------------------------------------------------------
|
|
93
|
+
/**
|
|
94
|
+
* Upsert an IoC: insert if new, merge sighting if existing.
|
|
95
|
+
* Upsert IoC:新建或合併觀測
|
|
96
|
+
*/
|
|
97
|
+
upsertIoC(input) {
|
|
98
|
+
const normalized = this.normalizeValue(input.type, input.value);
|
|
99
|
+
const now = new Date().toISOString();
|
|
100
|
+
const tags = input.tags ?? [];
|
|
101
|
+
const metadata = input.metadata ?? {};
|
|
102
|
+
// Try to find existing
|
|
103
|
+
const existing = this.db
|
|
104
|
+
.prepare('SELECT * FROM iocs WHERE type = ? AND normalized_value = ?')
|
|
105
|
+
.get(input.type, normalized);
|
|
106
|
+
if (existing) {
|
|
107
|
+
// Merge: increment sightings, update last_seen, update confidence, merge tags
|
|
108
|
+
const existingTags = JSON.parse(existing.tags);
|
|
109
|
+
const mergedTags = [...new Set([...existingTags, ...tags])];
|
|
110
|
+
const newConfidence = Math.max(existing.confidence, input.confidence);
|
|
111
|
+
const newLastSeen = now > existing.last_seen ? now : existing.last_seen;
|
|
112
|
+
this.db
|
|
113
|
+
.prepare(`UPDATE iocs SET
|
|
114
|
+
sightings = sightings + 1,
|
|
115
|
+
last_seen = ?,
|
|
116
|
+
confidence = ?,
|
|
117
|
+
tags = ?,
|
|
118
|
+
status = CASE WHEN status = 'expired' THEN 'active' ELSE status END,
|
|
119
|
+
updated_at = datetime('now')
|
|
120
|
+
WHERE id = ?`)
|
|
121
|
+
.run(newLastSeen, newConfidence, JSON.stringify(mergedTags), existing.id);
|
|
122
|
+
return this.getIoCById(existing.id);
|
|
123
|
+
}
|
|
124
|
+
// Insert new
|
|
125
|
+
const result = this.db
|
|
126
|
+
.prepare(`INSERT INTO iocs
|
|
127
|
+
(type, value, normalized_value, threat_type, source, confidence,
|
|
128
|
+
reputation_score, first_seen, last_seen, tags, metadata)
|
|
129
|
+
VALUES (?, ?, ?, ?, ?, ?, 50, ?, ?, ?, ?)`)
|
|
130
|
+
.run(input.type, input.value, normalized, input.threatType, input.source, input.confidence, now, now, JSON.stringify(tags), JSON.stringify(metadata));
|
|
131
|
+
return this.getIoCById(Number(result.lastInsertRowid));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Lookup a single IoC by type+value / 以 type+value 查詢單一 IoC
|
|
135
|
+
*/
|
|
136
|
+
lookupIoC(type, value) {
|
|
137
|
+
const normalized = this.normalizeValue(type, value);
|
|
138
|
+
const row = this.db
|
|
139
|
+
.prepare('SELECT * FROM iocs WHERE type = ? AND normalized_value = ?')
|
|
140
|
+
.get(type, normalized);
|
|
141
|
+
return row ? rowToRecord(row) : null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Lookup IoC with related threat count / 查詢 IoC 含相關威脅數
|
|
145
|
+
*/
|
|
146
|
+
lookupIoCWithContext(type, value, countThreats) {
|
|
147
|
+
const ioc = this.lookupIoC(type, value);
|
|
148
|
+
if (!ioc) {
|
|
149
|
+
return { found: false, relatedThreats: 0 };
|
|
150
|
+
}
|
|
151
|
+
const relatedThreats = type === 'ip' ? countThreats(ioc.normalizedValue) : 0;
|
|
152
|
+
return { found: true, ioc, relatedThreats };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get IoC by ID / 以 ID 取得 IoC
|
|
156
|
+
*/
|
|
157
|
+
getIoCById(id) {
|
|
158
|
+
const row = this.db.prepare('SELECT * FROM iocs WHERE id = ?').get(id);
|
|
159
|
+
return row ? rowToRecord(row) : null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get active IoCs by type with minimum reputation / 取得特定類型的活躍 IoC
|
|
163
|
+
*/
|
|
164
|
+
getActiveIoCsByType(type, minReputation, limit) {
|
|
165
|
+
const rows = this.db
|
|
166
|
+
.prepare(`SELECT * FROM iocs
|
|
167
|
+
WHERE type = ? AND status = 'active' AND reputation_score >= ?
|
|
168
|
+
ORDER BY reputation_score DESC
|
|
169
|
+
LIMIT ?`)
|
|
170
|
+
.all(type, minReputation, limit);
|
|
171
|
+
return rows.map(rowToRecord);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Search IoCs with filters and pagination / 以篩選條件搜尋 IoC
|
|
175
|
+
*/
|
|
176
|
+
searchIoCs(filters, pagination) {
|
|
177
|
+
const conditions = [];
|
|
178
|
+
const params = [];
|
|
179
|
+
if (filters.type) {
|
|
180
|
+
conditions.push('type = ?');
|
|
181
|
+
params.push(filters.type);
|
|
182
|
+
}
|
|
183
|
+
if (filters.source) {
|
|
184
|
+
conditions.push('source = ?');
|
|
185
|
+
params.push(filters.source);
|
|
186
|
+
}
|
|
187
|
+
if (filters.minReputation !== undefined) {
|
|
188
|
+
conditions.push('reputation_score >= ?');
|
|
189
|
+
params.push(filters.minReputation);
|
|
190
|
+
}
|
|
191
|
+
if (filters.status) {
|
|
192
|
+
conditions.push('status = ?');
|
|
193
|
+
params.push(filters.status);
|
|
194
|
+
}
|
|
195
|
+
if (filters.since) {
|
|
196
|
+
conditions.push('updated_at > ?');
|
|
197
|
+
params.push(filters.since);
|
|
198
|
+
}
|
|
199
|
+
if (filters.search) {
|
|
200
|
+
conditions.push('normalized_value LIKE ?');
|
|
201
|
+
params.push(`%${filters.search}%`);
|
|
202
|
+
}
|
|
203
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
204
|
+
const safePage = Math.max(1, pagination.page);
|
|
205
|
+
const safeLimit = Math.min(Math.max(1, pagination.limit), 1000);
|
|
206
|
+
const offset = (safePage - 1) * safeLimit;
|
|
207
|
+
const total = this.db.prepare(`SELECT COUNT(*) as count FROM iocs ${where}`).get(...params).count;
|
|
208
|
+
const rows = this.db
|
|
209
|
+
.prepare(`SELECT * FROM iocs ${where} ORDER BY reputation_score DESC, last_seen DESC LIMIT ? OFFSET ?`)
|
|
210
|
+
.all(...params, safeLimit, offset);
|
|
211
|
+
return {
|
|
212
|
+
items: rows.map(rowToRecord),
|
|
213
|
+
total,
|
|
214
|
+
page: safePage,
|
|
215
|
+
limit: safeLimit,
|
|
216
|
+
hasMore: offset + safeLimit < total,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Batch update reputation scores / 批次更新信譽分數
|
|
221
|
+
*/
|
|
222
|
+
batchUpdateReputation(updates) {
|
|
223
|
+
const stmt = this.db.prepare("UPDATE iocs SET reputation_score = ?, updated_at = datetime('now') WHERE id = ?");
|
|
224
|
+
const updateAll = this.db.transaction((items) => {
|
|
225
|
+
for (const u of items) {
|
|
226
|
+
stmt.run(Math.max(0, Math.min(100, Math.round(u.reputationScore))), u.id);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
updateAll(updates);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Expire stale IoCs / 過期未活躍的 IoC
|
|
233
|
+
*/
|
|
234
|
+
expireStaleIoCs(olderThan) {
|
|
235
|
+
const result = this.db
|
|
236
|
+
.prepare("UPDATE iocs SET status = 'expired', updated_at = datetime('now') WHERE status = 'active' AND last_seen < ?")
|
|
237
|
+
.run(olderThan);
|
|
238
|
+
return result.changes;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Delete expired IoCs beyond retention / 刪除超齡的已過期 IoC
|
|
242
|
+
*/
|
|
243
|
+
purgeExpiredIoCs(olderThan) {
|
|
244
|
+
const result = this.db
|
|
245
|
+
.prepare("DELETE FROM iocs WHERE status = 'expired' AND updated_at < ?")
|
|
246
|
+
.run(olderThan);
|
|
247
|
+
return result.changes;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get IoC counts by type / 取得各類型 IoC 數量
|
|
251
|
+
*/
|
|
252
|
+
getIoCCountsByType() {
|
|
253
|
+
const rows = this.db
|
|
254
|
+
.prepare("SELECT type, COUNT(*) as count FROM iocs WHERE status = 'active' GROUP BY type")
|
|
255
|
+
.all();
|
|
256
|
+
const result = {};
|
|
257
|
+
for (const r of rows) {
|
|
258
|
+
result[r.type] = r.count;
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get top malicious IoCs / 取得最高威脅度 IoC
|
|
264
|
+
*/
|
|
265
|
+
getTopMaliciousIoCs(limit) {
|
|
266
|
+
const rows = this.db
|
|
267
|
+
.prepare("SELECT * FROM iocs WHERE status = 'active' ORDER BY reputation_score DESC LIMIT ?")
|
|
268
|
+
.all(limit);
|
|
269
|
+
return rows.map(rowToRecord);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get total active IoC count / 取得活躍 IoC 總數
|
|
273
|
+
*/
|
|
274
|
+
getTotalActiveCount() {
|
|
275
|
+
return this.db.prepare("SELECT COUNT(*) as count FROM iocs WHERE status = 'active'").get().count;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=ioc-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ioc-store.js","sourceRoot":"","sources":["../src/ioc-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Handlers for advanced analytics
|
|
3
|
+
* 進階分析查詢處理器
|
|
4
|
+
*
|
|
5
|
+
* Provides timeseries, geo distribution, trends, and MITRE heatmap queries.
|
|
6
|
+
*
|
|
7
|
+
* @module @panguard-ai/threat-cloud/query-handlers
|
|
8
|
+
*/
|
|
9
|
+
import type Database from 'better-sqlite3';
|
|
10
|
+
import type { TimeSeriesPoint, GeoDistributionEntry, TrendEntry, MitreHeatmapEntry, EnhancedStats } from './types.js';
|
|
11
|
+
export declare class QueryHandlers {
|
|
12
|
+
private readonly db;
|
|
13
|
+
constructor(db: Database.Database);
|
|
14
|
+
/**
|
|
15
|
+
* Time-series query: event counts grouped by time bucket.
|
|
16
|
+
* 時間序列查詢:依時間桶分組的事件計數
|
|
17
|
+
*/
|
|
18
|
+
getTimeSeries(granularity?: 'hour' | 'day' | 'week', since?: string, attackType?: string): TimeSeriesPoint[];
|
|
19
|
+
/**
|
|
20
|
+
* Geographic distribution query.
|
|
21
|
+
* 地理分佈查詢
|
|
22
|
+
*/
|
|
23
|
+
getGeoDistribution(since?: string): GeoDistributionEntry[];
|
|
24
|
+
/**
|
|
25
|
+
* Trend analysis: compare current period with previous period.
|
|
26
|
+
* 趨勢分析:比較當前與前一期間
|
|
27
|
+
*/
|
|
28
|
+
getTrends(periodDays?: number): TrendEntry[];
|
|
29
|
+
/**
|
|
30
|
+
* MITRE ATT&CK technique heatmap.
|
|
31
|
+
* MITRE ATT&CK 技術熱力圖
|
|
32
|
+
*/
|
|
33
|
+
getMitreHeatmap(since?: string): MitreHeatmapEntry[];
|
|
34
|
+
/**
|
|
35
|
+
* Enhanced stats combining all data sources.
|
|
36
|
+
* 增強統計:整合所有資料來源
|
|
37
|
+
*/
|
|
38
|
+
getEnhancedStats(): EnhancedStats;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=query-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-handlers.d.ts","sourceRoot":"","sources":["../src/query-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAElD;;;OAGG;IACH,aAAa,CACX,WAAW,GAAE,MAAM,GAAG,KAAK,GAAG,MAAc,EAC5C,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,eAAe,EAAE;IAkCpB;;;OAGG;IACH,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAkC1D;;;OAGG;IACH,SAAS,CAAC,UAAU,GAAE,MAAU,GAAG,UAAU,EAAE;IAmD/C;;;OAGG;IACH,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAiCpD;;;OAGG;IACH,gBAAgB,IAAI,aAAa;CAsGlC"}
|