Oracle 11G数据库审计监控设置指南
Oracle 11G 开启审计监控数据库
1 创建审计数据专用表空间
由于审计数据可能占用大量空间,所以放入默认的system表空间显然是不合理的,所以我们应该创建专门的表空间以及用户来保存审计数据,这样才是一个比较合理的规划。
CREATE TABLESPACE AUDIT_TBS
DATAFILE
'/data2/app/oracle/datafile/AUDIT_TBS1'SIZE 2048M AUTOEXTEND ON NEXT 512M MAXSIZE UNLIMITED,
'/data2/app/oracle/datafile/AUDIT_TBS2'SIZE 2048M AUTOEXTEND ON NEXT 512M MAXSIZE UNLIMITED
SEGMENT SPACE MANAGEMENT AUTO;
2 查看相关信息
select table_name,tablespace_name from dba_tables where table_name='AUD$';
1 AUD$ SYSTEM
select COLUMN_NAME,SEGMENT_NAME,tablespace_name from dba_lobs where table_name ='AUD$';
1 SQLBIND SYS_LOB0000000407C00040$$ SYSTEM
2 SQLTEXT SYS_LOB0000000407C00041$$ SYSTEM
select index_name,tablespace_name from dba_indexes where table_name ='AUD$';
1 SYS_IL0000000407C00040$$ SYSTEM
2 SYS_IL0000000407C00041$$ SYSTEM
3 在线移动至新的表空间
3.1 清空历史审计信息
由于当前数据库可能已经包含过去的审计信息,所以迁移的过程中比较慢,为了解决这个问题,可以先将现有的审计信息清空(当然是业务允许情况下),清空语句如下:
sqlplus / as sysdba
truncate table sys.aud$;
3.2 迁移表空间
sqlplus / as sysdba
alter table aud$ move tablespace AUDIT_TBS;
alter table AUD$ move lob(SQLBIND) store as SYS_LOB0000000407C00040$$ (tablespace AUDIT_TBS);
alter table AUD$ move lob(SQLTEXT) store as SYS_LOB0000000407C00041$$(tablespace AUDIT_TBS);
alter table AUD$ move lob(SQLBIND) store as SYS_IL0000000407C00040$$ (tablespace AUDIT_TBS);
alter table AUD$ move lob(SQLTEXT) store as SYS_IL0000000407C00041$$(tablespace AUDIT_TBS);
注:上面的SYS_LOB0000000407C00040$$类似的文件名称是由步骤2查询而得。
3.3 开启审计
sqlplus / as sysdb
alter system set audit_sys_operations=true scope=spfile;
alter system set audit_trail=db,extended scope=spfile;
shutdown immediate
startup
4 审计功能的一些相关维护
以下所有语句都在SYS用户下执行
sqlplus / as sysdba
4.1 审计数据迁移(另一种方案)
BEGIN
DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
AUDIT_TRAIL_LOCATION_VALUE => 'AUDIT_TBS'
);
END;
/
4.2 审计数据自动清理
由于审计日志的数据可能比较多,所以需要定期清理数据,保证数据库相关性能
begin
dbms_audit_mgmt.init_cleanup(
audit_trail_type => dbms_audit_mgmt.audit_trail_all,
default_cleanup_interval => 24 );
end;
/
这个INIT_CLEANUP过程设计到两个参数:
- audit_trail_type:指要设置的清理类型,这里是audit_trail_db_std,标准的数据库审计跟踪,即aud$表。
- default_cleanup_interval:这个值表示每隔多少时间执行清理任务,24即24小时。
相关审计类型:
- audit_trail_aud_std:The standard AUD$ audit trail in the database
- audit_trail_fga_std:The FGA_LOG$ table, for Fine Grained Auditing
- audit_trail_db_std:Both standard and FGA audit trails
- audit_trail_os:The OS audit trail
- audit_trail_XML:The XML audit trail
- audit_trail_files:Both OS and XML audit trails
- audit_trail_all:All of the above
设置完初始化清理参数后,实际上在调用清理任务时,会发现并没有达到你的预期,可能数据一条都没有清理掉,我们还需要设置另一个过程参数SET_LAST_ARCHIVE_TIMESTAMP,它的作用是告诉清理进程一个审计归档时间戳,
这个过程接收三个参数:
- audit_trail_type:要清理的审计类型,如audit_trail_aud_std
- last_archive_time:最后一次归档时间,可以手工设置
- rac_instance_number:RAC的话可以指定实例号
代码如下
begin
dbms_audit_mgmt.set_last_archive_timestamp(
audit_trail_type => dbms_audit_mgmt.audit_trail_aud_std,
last_archive_time =>
to_timestamp('2020-05-26 10:00:00','YYYY-MM-DD HH24:MI:SS'),
rac_instance_number => null
);
end;
/
执行上段程序后,你可以在DBA_AUDIT_MGMT_LAST_ARCH_TS视图中查到相关信息。
有了归档时间后,就可以执行真正的清理程序了。
begin
dbms_audit_mgmt.clean_audit_trail(
audit_trail_type => dbms_audit_mgmt.audit_trail_aud_std,
use_last_arch_timestamp => TRUE
);
end;
/
- audit_trail_type表示清理的审计类型,
- use_last_arch_timestamp => TRUE,表示用最后的归档时间,如果为false,将会清理掉audit_trail_aud_std类型的所有审计信息。
上面是手工清理的方法,设置了清理时间点后运行清理过程。下一步看自动清理怎么做:
将采用数据库的自动任务来实现,第一个任务,自动产生清理时间点:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'DAILY_AUDIT_ARCHIVE_TIMESTAMP',
job_type => 'PLSQL_block',
job_action => 'BEGIN DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(AUDIT_TRAIL_TYPE =>
DBMS_AUDIT_MGMT.audit_trail_all,LAST_ARCHIVE_TIME => sysdate-1); END;',
start_date => sysdate,
repeat_interval => 'FREQ=HOURLY;INTERVAL=24',
enabled => TRUE,
comments => 'Create an archive timestamp'
);
END;
/
第二个任务,根据时间点自动清理:
BEGIN
DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.audit_trail_all,
AUDIT_TRAIL_PURGE_INTERVAL => 24 ,
AUDIT_TRAIL_PURGE_NAME => 'DAILY_AUDIT_PURGE_JOB',
USE_LAST_ARCH_TIMESTAMP => TRUE
);
END;
/
删除DAILY_AUDIT_PURGE_JOB与DAILY_AUDIT_ARCHIVE_TIMESTAMP
exec dbms_scheduler.drop_job( job_name => 'SYS.DAILY_AUDIT_ARCHIVE_TIMESTAMP' , force => TRUE);
exec SYS.DBMS_AUDIT_MGMT.DROP_PURGE_JOB( AUDIT_TRAIL_PURGE_NAME => 'DAILY_AUDIT_PURGE_JOB');
5 将审计权限赋予其他用户
sqlplus / as sysdba
grant select on sys.aud$ to dataaly; -----赋予新用户查询审计信息
grant select on sys.dba_fga_audit_trail to dataaly; ----赋予新用户查询审计信息
6 查询所有可以设定的审计类型
select user_name,audit_option,success,failure from dba_stmt_audit_opts
union
select USER_NAME,privilege,success,failure from dba_priv_audit_opts;
7 下表中总结了Oracle数据库中不同类型的审计。
审 计 类 型 | 说 明 |
---|---|
语句审计 | 按照语句类型审计SQL语句,而不论访问何种特定的模式对象。也可以在数据库中指定一个或多个用户,针对特定的语句审计这些用户 |
权限审计 | 审计系统权限,例如CREATE TABLE或ALTER INDEX。和语句审计一样,权限审计可以指定一个或多个特定的用户作为审计的目标 |
模式对象 | 审计审计特定模式对象上运行的特定语句(例如,DEPARTMENTS表上的UPDATE语句)。模式对象审计总是应用于数据库中的所有用户 |
细粒度的审计 | 根据访问对象的内容来审计表访问和权限。使用程序包DBMS_FGA来建立特定表上的策略 |
下面几节介绍DBA如何管理系统和对象权限使用的审计。当需要一定的粒度时,DBA可以使用细粒度的审计来监控对表中某些行或列的访问,而不仅仅是是否访问表。
和审计相关的主要参数
SQL>show parameter audit
audit_file_dest
audit_sys_operations
audit_trail
audit_sys_operations:
- 默认为false,当设置为true时,所有sys用户(包括以sysdba,sysoper身份登录的用户)的操作都会被记录,audit trail不会写在aud 表 中 , 这 个 很 好 理 解 , 如 果 数 据 库 还 未 启 动 a u d 表中,这个很好理解,如果数据库还未启动aud 表中,这个很好理解,如果数据库还未启动aud不可用,那么像conn /as sysdba这样的连接信息,只能记录在其它地方。如果是Windows平台,audti trail会记录在windows的事件管理中,如果是linux/Unix平台则会记录在audit_file_dest参数指定的文件中。
audit_trail:
- None:是默认值,不做审计;
- DB:将audit trail 记录在数据库的审计相关表中,如aud$,审计的结果只有连接信息;
- DB,Extended:这样审计结果里面除了连接信息还包含了当时执行的具体语句;
- OS:将audit trail 记录在操作系统文件中,文件名由audit_file_dest参数指定;
7.1 语句审计
所有类型的审计都使用audit命令来打开审计,使用noaudit命令来关闭审计。对于语句审计,audit命令的格式看起来如下所示:
AUDIT sql_statement_clause BY {SESSION | Access} WHENEVER [NOT] SUCCESSFUL;
sql_statement_clause包含很多条不同的信息,例如希望审计的SQL语句类型以及审计么人。
此外,希望在每次动作发生时都对其进行审计(by access)或者只审计一次(by session)。默认是by session。
有时希望审计成功的动作:没有生成错误消息的语句。对于这些语句,添加whenever successful。而有时只关心使用审计语句的命令是否失败,失败原因是权限违犯、用完表空间中的空间还是语法错误。对于这些情况,使用 whenever not successful。
对于大多数类别的审计方法,如果确实希望审计所有类型的表访问或某个用户的任何权限,则可以指定all而不是单个的语句类型或对象。
表1列出了可以审计的语句类型,并且在每个类别中包含了相关语句的简要描述。如果指定all,则审计该列表中的任何语句。然而,表2中的语句类型在启用审计时不属于all类别;必须在audit命令中显式地指定它们。
表1 包括在ALL类别中的可审计语句
语 句 选 项 | SQL操作 |
---|---|
ALTER SYSTEM | 所有ALTER SYSTEM选项,例如,动态改变实例参数,切换到下一个日志文件组,以及终止用户会话 |
CLUSTER | CREATE、ALTER、DROP或TRUNCATE集群 |
CONTEXT | CREATE CONTEXT或DROP CONTEXT |
DATABASE LINK | CREATE或DROP数据库链接 |
DIMENSION | CREATE、ALTER或DROP维数 |
DIRECTORY | CREATE或DROP目录 |
INDEX | CREATE、ALTER或DROP索引 |
MATERIALIZED VIEW | CREATE、ALTER或DROP物化视图 |
NOT EXISTS | 由于不存在的引用对象而造成的SQL语句的失败 |
PROCEDURE | CREATE或DROP FUNCTION、LIBRARY、PACKAGE、PACKAGE BODY或PROCEDURE |
PROFILE | CREATE、ALTER或DROP配置文件 |
PUBLIC DATABASE LINK | CREATE或DROP公有数据库链接 |
PUBLIC SYNONYM | CREATE或DROP公有同义词 |
ROLE | CREATE、ALTER、DROP或SET角色 |
ROLLBACK SEGMENT | CREATE、ALTER或DROP回滚段 |
SEQUENCE | CREATE或DROP序列 |
SESSION | 登录和退出 |
SYNONYM | CREATE或DROP同义词 |
SYSTEM AUDIT | 系统权限的AUDIT或NOAUDIT |
SYSTEM GRANT | GRANT或REVOKE系统权限和角色 |
TABLE | CREATE、DROP或TRUNCATE表 |
TABLESPACE | CREATE、ALTER或DROP表空间 |
TRIGGER | CREATE、ALTER(启用/禁用)、DROP触发器;具有ENABLE ALL TRIGGERS或DISABLE ALL TRIGGERS的ALTER TABLE |
TYPE | CREATE、ALTER和DROP类型以及类型主体 |
USER | CREATE、ALTER或DROP用户 |
VIEW | CREATE或DROP视图 |
表2 显式指定的语句类型
语 句 选 项 | SQL 操 作 |
---|---|
ALTER SEQUENCE | 任何ALTER SEQUENCE命令 |
ALTER TABLE | 任何ALTER TABLE命令 |
COMMENT TABLE | 添加注释到表、视图、物化视图或它们中的任何列 |
DELETE TABLE | 删除表或视图中的行 |
EXECUTE PROCEDURE | 执行程序包中的过程、函数或任何变量或游标 |
GRANT DIRECTORY | GRANT或REVOKE DIRECTORY对象上的权限 |
GRANT PROCEDURE | GRANT或REVOKE过程、函数或程序包上的权限 |
GRANT SEQUENCE | GRANT或REVOKE序列上的权限 |
GRANT TABLE | GRANT或REVOKE表、视图或物化视图上的权限 |
GRANT TYPE | GRANT或REVOKE TYPE上的权限 |
INSERT TABLE | INSERT INTO表或视图 |
LOCK TABLE | 表或视图上的LOCK TABLE命令 |
SELECT SEQUENCE | 引用序列的CURRVAL或NEXTVAL的任何命令 |
SELECT TABLE | SELECT FROM表、视图或物化视图 |
UPDATE TABLE | 在表或视图上执行UPDATE |
注意:
从Oracle Database 11g开始,只有在初始参数AUDIT_TRAIL被设置为DB_EXTENDED时,才填充DBA_AUDIT_TRAIL中的列SQL_TEXT和SQL_BIND。默认情况下,AUDIT_TRAIL的值是DB。
SQL> audit index by dataaly;
Audit succeeded.
为了关闭HR.JOBS表上KSHELTON的审计,可以使用noaudit命令,如下所示:
SQL> noaudit index by dataaly;
Noaudit succeeded.
也可能希望按常规方式审计成功的和不成功的登录,这需要两个audit命令:
SQL> audit session whenever successful;
Audit succeeded.
SQL> audit session whenever not successful;
Audit succeeded.
7.2 权限审计
审计系统权限具有与语句审计相同的基本语法,但审计系统权限是在sql_stateme nt_clause中,而不是在语句中,指定系统权限。
例如,可能希望将ALTER TABLESPACE权限授予所有的DBA,但希望在发生这种情况时生成审计记录。启用对这种权限的审计的命令看起来类似于语句审计:
SQL> audit alter tablespace by access whenever successful;
Audit succeeded.
每次成功使用ALTER TABLESPACE权限时,都会将一行内容添加到SYS.AUD$。
使用SYSDBA和SYSOPER权限或者以SYS用户连接到数据库的系统管理员可以利用特殊的审计。为了启用这种额外的审计级别,可以设置初始参数AUDIT_SYS_OPERATIONS为TRUE。
这种审计记录发送到与操作系统审计记录相同的位置。因此,这个位置是和操作系统相关的。当使用其中一种权限时执行的所有SQL语句,以及作为用户SYS执行的任何SQL语句,都会发送到操作系统审计位置。
7.3 模式对象审计
审计对各种模式对象的访问看起来类似于语句审计和权限审计:
AUDIT schema_object_clause BY {SESSION | ACCESS}
WHENEVER [NOT] SUCCESSFUL;
schema_object_clause指定对象访问的类型以及访问的对象。可以审计特定对象上14种不同的操作类型,下表中列出了这些操作。
对 象 选 项 | 说 明 |
---|---|
ALTER | 改变表、序列或物化视图 |
AUDIT | 审计任何对象上的命令 |
COMMENT | 添加注释到表、视图或物化视图 |
DELETE | 从表、视图或物化视图中删除行 |
EXECUTE | 执行过程、函数或程序包 |
FLASHBACK | 执行表或视图上的闪回操作 |
GRANT | 授予任何类型对象上的权限 |
INDEX | 创建表或物化视图上的索引 |
INSERT | 将行插入表、视图或物化视图中 |
LOCK | 锁定表、视图或物化视图 |
READ | 对DIRECTORY对象的内容执行读操作 |
RENAME | 重命名表、视图或过程 |
SELECT | 从表、视图、序列或物化视图中选择行 |
UPDATE | 更新表、视图或物化视图 |
如果希望审计HR.JOBS表上的所有insert和update命令,而不管谁正在进行更新,则每次该动作发生时,都可以使用如下所示的audit命令:
SQL> audit insert, update on hr.jobs by access whenever successful;
Audit successful.
7.4 细粒度的审计
从Oracle9i开始,通过引入细粒度的对象审计,或称为FGA,审计变得更为关注某个方面,并且更为精确。由称为DBMS_FGA的PL/SQL程序包实现FGA。
使用标准的审计,可以轻松发现访问了哪些对象以及由谁访问,但无法知道访问了哪些行或列。细粒度的审计可解决这个问题,它不仅为需要访问的行指定谓词(或where子句),还指定了表中访问的列。通过只在访问某些行和列时审计对表的访问,可以极大地减少审计表条目的数量。
程序包DBMS_FGA具有4个过程:
ADD_POLICY | 添加使用谓词和审计列的审计策略 |
---|---|
DROP_POLICY | 删除审计策略 |
DISABLE_POLICY | 禁用审计策略,但保留与表或视图关联的策略 |
ENABLE_POLICY | 启用策略 |
用户TAMARA通常每天访问HR.EMPLOYEES表,查找雇员的电子邮件地址。系统管理员怀疑TAMARA正在查看经理们的薪水信息,因此他们建立一个FGA策略,用于审计任何经理对SALARY列的任何访问:
begin
dbms_fga.add_policy(
object_schema => 'HR',
object_name => 'EMPLOYEES',
policy_name => 'SAL_SELECT_AUDIT',
audit_condition => 'instr(job_id,''_MAN'') > 0',
audit_column => 'SALARY'
);
end;
可以使用数据字典视图DBA_FGA_AUDIT_TRAIL访问细粒度审计的审计记录。如果一般需要查看标准的审计行和细粒度的审计行,则数据字典视图DBA_COMMON_AUDIT_TRAIL结合了这两种审计类型中的行。
继续看示例,用户TAMARA运行了如下两个SQL查询:
SQL> select employee_id, first_name, last_name, email from hr.employees
2 where employee_id = 114;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL
----------- ------------------ --------------------- --------------
114 Den Raphaely DRAPHEAL
1 row selected.
SQL> select employee_id, first_name, last_name, salary from hr.employees
2 where employee_id = 114;
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY
----------- ------------------ ----------------------- ----------
114 Den Raphaely 11000
1 row selected.
第一个查询访问经理信息,但没有访问SALARY列。第二个查询与第一个查询相同,但是访问了SALARY列,因此触发了FGA策略,从而在审计跟踪中生成了一行:
SQL> select to_char(timestamp,'mm/dd/yy hh24:mi') timestamp,
2 object_schema, object_name, policy_name, statement_type
3 from dba_fga_audit_trail
4 where db_user = 'TAMARA';
TIMESTAMP OBJECT_SCHEMA OBJECT_NAME POLICY_NAME STATEMENT_TYPE
-------------- ------------- ------------- ---------------- --------------
08/12/07 18:07 HR EMPLOYEES SAL_SELECT_AUDIT SELECT
1 row selected.
因为在本章前面的VPD示例中建立了细粒度的访问控制来阻止对SALARY列的未授权访问,因此需要加倍检查策略函数,确保仍然正确限制了SALARY信息。细粒度的审计以及标准审计是确保首先正确建立授权策略的好方法。
7.5 与审计相关的数据字典视图
下表包含了与审计相关的数据字典视图。
数据字典视图 | 说 明 |
---|---|
AUDIT_ACTIONS | 包含审计跟踪动作类型代码的描述,例如INSERT、DROP VIEW、DELETE、LOGON和LOCK |
DBA_AUDIT_OBJECT | 与数据库中对象相关的审计跟踪记录 |
DBA_AUDIT_POLICIES | 数据库中的细粒度审计策略 |
DBA_AUDIT_SESSION | 与CONNECT和DISCONNECT相关的所有审计跟踪记录 |
DBA_AUDIT_STATEMENT | 与GRANT、REVOKE、AUDIT、NOAUDIT和ALTER SYSTEM命令相关的审计跟踪条目 |
DBA_AUDIT_TRAIL | 包含标准审计跟踪条目。USER_AUDIT_TRAILUSER_TRAIL_AUDIT只包含已连接用户的审计行 |
DBA_FGA_AUDIT_TRAIL | 细粒度审计策略的审计跟踪条目 |
DBA_COMMON_AUDIT_TRAIL | 将标准的审计行和细粒度的审计行结合在一个视图中 |
DBA_OBJ_AUDIT_OPTS | 对数据库对象生效的审计选项 |
DBA_PRIV_AUDIT_OPTS | 对系统权限生效的审计选项 |
DBA_STMT_AUDIT_OPTS | 对语句生效的审计选项 |
7.6 保护审计跟踪
审计跟踪自身需要受到保护,特别是在非系统用户必须访问表SYS.AUD$时。内置的角色DELETE_ANY_CATALOG是非SYS用户可以访问审计跟踪的一种方法(例如,归档和截取审计跟踪,以确保它不会影响到SYS表空间中其他对象的空间需求)。
为了建立对审计跟踪自身的审计,以SYSDBA身份连接到数据库,并运行下面的命令:
SQL> audit all on sys.aud$ by access;
Audit succeeded.
现在,所有针对表SYS.AUD 的 动 作 , 包 括 select 、insert、update 和 delete,都记录在 SYS.AUD的动作,包括select、insert、update和delete,都记录在SYS.AUD 的动作,包括select、insert、update和delete,都记录在SYS.AUD自身中。但是,您可能会问,如果某个人删除了标识对表SYS.AUD 访 问 的 审 计 记 录 , 这 时 会 发 生 什 么 ? 此 时 将 删 除 表 中 的 行 , 但 接 着 插 入 另 一 行 , 记 录 行 的 删 除 。 因 此 , 总 是 存 在 一 些 针 对 SYS.AUD 访问的审计记录,这时会发生什么?此时将删除表中的行,但接着插入另一行,记录行的删除。因此,总是存在一些针对SYS.AUD 访问的审计记录,这时会发生什么?此时将删除表中的行,但接着插入另一行,记录行的删除。因此,总是存在一些针对SYS.AUD表的(有意的或偶然的)活动的证据。此外,如果将AUDIT_SYS _OPERATIONS设置为True,使用as sysdba、as sysoper或以SYS自身连接的任何会话将记录到操作系统审计位置中,甚至Oracle DBA可能都无法访问该位置。因此,有许多合适的安全措施,用于确保记录数据库中所有权限的活动,以及隐藏该活动的任何尝试。
7.7 启用增强的审计
从Oracle Database 11g开始,数据库配置助手(Database Configuration Assistant,DBCA)很容易启用默认的(增强的)审计。虽然记录审计信息有一些系统开销,但兼容性需求(例如,Sarbanes-Oxley法案中规定的兼容性需求)要求严格监控所有业务操作,包括数据库中与安全相关的操作。
可以在创建数据库时或在数据库已经创建之后使用DBCA配置默认审计。如果已经改变了很多审计设置,并想要将审计选项重置为基线值,则在数据库已创建之后使用DBCA配置默认审计就非常有用。
除将初始参数AUDIT_TRAIL的值设置为DB外,默认审计设置还审计audit role命令本身。另外,在Audited Privileges选项卡的Oracle Enterprise Manager Audit Settings页面中,可以查看默认的审计权限。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.lsjlt.com)。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341