mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-01-03 08:39:04 +08:00
feat: Add OB11GroupGrayTipEvent for detecting forged gray tip attacks (#1492)
* feat: Add OB11GroupGrayTipEvent for detecting forged gray tip attacks - Add new OB11GroupGrayTipEvent class to report unknown gray tip messages - Modify parseOtherJsonEvent to detect forged gray tips by checking senderUin - Real system gray tips have senderUin='0', forged ones expose attacker's QQ - Include message_id in event for downstream recall capability - Add try/catch for JSON.parse to handle malformed content - Use Number() for consistent type conversion * fix: simplify logWarn to match upstream style * fix: remove extra closing brace that broke class structure * fix: add validation for malformed title gray tip events
This commit is contained in:
parent
b241881c74
commit
2d3f4e696b
@ -19,6 +19,7 @@ import { OB11GroupCardEvent } from '@/napcat-onebot/event/notice/OB11GroupCardEv
|
||||
import { OB11GroupPokeEvent } from '@/napcat-onebot/event/notice/OB11PokeEvent';
|
||||
import { OB11GroupEssenceEvent } from '@/napcat-onebot/event/notice/OB11GroupEssenceEvent';
|
||||
import { OB11GroupTitleEvent } from '@/napcat-onebot/event/notice/OB11GroupTitleEvent';
|
||||
import { OB11GroupGrayTipEvent } from '@/napcat-onebot/event/notice/OB11GroupGrayTipEvent';
|
||||
import { OB11GroupUploadNoticeEvent } from '../event/notice/OB11GroupUploadNoticeEvent';
|
||||
import { OB11GroupNameEvent } from '../event/notice/OB11GroupNameEvent';
|
||||
import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
|
||||
@ -206,15 +207,24 @@ export class OneBotGroupApi {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async parseOtherJsonEvent (msg: RawMessage, jsonStr: string, context: InstanceContext) {
|
||||
const json = JSON.parse(jsonStr);
|
||||
const type = json.items[json.items.length - 1]?.txt;
|
||||
async parseOtherJsonEvent (msg: RawMessage, jsonGrayTipElement: GrayTipElement['jsonGrayTipElement'], context: InstanceContext) {
|
||||
let json: { items?: { txt?: string; param?: string[] }[] };
|
||||
try {
|
||||
json = JSON.parse(jsonGrayTipElement.jsonStr);
|
||||
} catch (e) {
|
||||
context.logger.logWarn('灰条消息JSON解析失败', jsonGrayTipElement.jsonStr, e);
|
||||
return undefined;
|
||||
}
|
||||
const type = json.items?.[json.items.length - 1]?.txt;
|
||||
await this.core.apis.GroupApi.refreshGroupMemberCachePartial(msg.peerUid, msg.senderUid);
|
||||
if (type === '头衔') {
|
||||
const memberUin = json.items[1].param[0];
|
||||
const title = json.items[3].txt;
|
||||
const memberUin = json.items?.[1]?.param?.[0];
|
||||
const title = json.items?.[3]?.txt;
|
||||
context.logger.logDebug('收到群成员新头衔消息', json);
|
||||
if (memberUin == null || title == null) {
|
||||
context.logger.logWarn('收到格式异常的群成员新头衔灰条消息', json);
|
||||
return undefined;
|
||||
}
|
||||
return new OB11GroupTitleEvent(
|
||||
this.core,
|
||||
+msg.peerUid,
|
||||
@ -225,6 +235,27 @@ export class OneBotGroupApi {
|
||||
context.logger.logDebug('收到机器人被踢消息', json);
|
||||
} else {
|
||||
context.logger.logWarn('收到未知的灰条消息', json);
|
||||
|
||||
// 如果有真实发送者(非0),生成事件上报,可用于检测和撤回伪造灰条
|
||||
const senderUin = Number(msg.senderUin) || 0;
|
||||
if (senderUin !== 0) {
|
||||
const peer = { chatType: ChatType.KCHATTYPEGROUP, guildId: '', peerUid: msg.peerUid };
|
||||
const messageId = MessageUnique.createUniqueMsgId(peer, msg.msgId);
|
||||
return new OB11GroupGrayTipEvent(
|
||||
this.core,
|
||||
+msg.peerUin,
|
||||
senderUin,
|
||||
messageId,
|
||||
jsonGrayTipElement.busiId,
|
||||
jsonGrayTipElement.jsonStr,
|
||||
{
|
||||
msgSeq: msg.msgSeq,
|
||||
msgTime: msg.msgTime,
|
||||
msgId: msg.msgId,
|
||||
json,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -376,7 +407,7 @@ export class OneBotGroupApi {
|
||||
return await this.parse51TypeEvent(msg, grayTipElement);
|
||||
} else {
|
||||
console.log('Unknown JSON event:', grayTipElement.jsonGrayTipElement, JSON.stringify(grayTipElement));
|
||||
return await this.parseOtherJsonEvent(msg, grayTipElement.jsonGrayTipElement.jsonStr, this.core.context);
|
||||
return await this.parseOtherJsonEvent(msg, grayTipElement.jsonGrayTipElement, this.core.context);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
35
packages/napcat-onebot/event/notice/OB11GroupGrayTipEvent.ts
Normal file
35
packages/napcat-onebot/event/notice/OB11GroupGrayTipEvent.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
|
||||
/**
|
||||
* 群灰条消息事件
|
||||
* 用于上报未知类型的灰条消息,便于下游检测和处理伪造灰条攻击
|
||||
*/
|
||||
export class OB11GroupGrayTipEvent extends OB11BaseNoticeEvent {
|
||||
notice_type = 'notify';
|
||||
sub_type = 'gray_tip';
|
||||
group_id: number;
|
||||
user_id: number; // 真实发送者QQ(如果是伪造的灰条,这就是攻击者)
|
||||
message_id: number; // 消息ID,可用于撤回
|
||||
busi_id: string; // 业务ID
|
||||
content: string; // 灰条内容(JSON字符串)
|
||||
raw_info: unknown; // 原始信息
|
||||
|
||||
constructor (
|
||||
core: NapCatCore,
|
||||
groupId: number,
|
||||
userId: number,
|
||||
messageId: number,
|
||||
busiId: string,
|
||||
content: string,
|
||||
rawInfo: unknown
|
||||
) {
|
||||
super(core);
|
||||
this.group_id = groupId;
|
||||
this.user_id = userId;
|
||||
this.message_id = messageId;
|
||||
this.busi_id = busiId;
|
||||
this.content = content;
|
||||
this.raw_info = rawInfo;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user