2026年CentOS上SQLPlus安全设置完全指南(2026)

一、SQLPlus安全概述

1.1 为什么安全设置重要?

在CentOS服务器上运行Oracle数据库时,SQLPlus是主要的数据库访问工具。未经安全加固的SQLPlus环境可能面临以下风险:

  1. 未授权访问:弱密码或默认账户被攻击者利用
  2. 数据泄露:敏感数据通过SQL注入等方式被窃取
  3. 权限滥用:过度授权导致数据被恶意修改或删除
  4. 审计缺失:无法追踪用户操作,难以及时发现异常

1.2 安全策略概览

安全领域 核心措施 优先级
账户管理 强密码策略、最小权限原则
网络安全 防火墙、SSL/TLS加密
SQL注入防护 参数化查询、输入验证
审计监控 操作日志、异常告警
文件权限 配置文件保护、日志加密

二、账户与权限安全

2.1 密码策略配置

-- 创建Profile并设置密码策略
CREATE PROFILE secure_profile LIMIT
    FAILED_LOGIN_ATTEMPTS 5        -- 连续失败5次后锁定
    PASSWORD_LOCK_TIME 1           -- 锁定1天
    PASSWORD_LIFE_TIME 90          -- 密码90天有效
    PASSWORD_REUSE_MAX 3           -- 密码至少换3次后才能重用
    PASSWORD_REUSE_DELAY 30;       -- 30天内不能重用旧密码

-- 将Profile分配给用户
ALTER USER scott PROFILE secure_profile;

-- 设置强密码(Oracle 12c+)
ALTER USER scott IDENTIFIED BY "Str0ngP@ssw0rd!";

-- 检查用户密码过期时间
SELECT username, profile, account_status, expiry_date 
FROM dba_users 
WHERE account_status = 'EXPIRED';

2.2 最小权限原则

-- 创建应用专用账户
CREATE USER app_user IDENTIFIED BY "AppP@ss123!" 
    DEFAULT TABLESPACE users
    TEMPORARY TABLESPACE temp;

-- 按需授予权限(不要授予DBA)
GRANT CREATE SESSION TO app_user;           -- 只允许连接
GRANT SELECT ON scott.emp TO app_user;      -- 只读表emp
GRANT INSERT, UPDATE ON scott.orders TO app_user;  -- 读写orders表

-- 撤销不必要的权限
REVOKE DBA FROM app_user;
REVOKE DELETE ANY TABLE FROM app_user;

-- 查看用户权限
SELECT * FROM dba_tab_privs WHERE grantee = 'APP_USER';
SELECT * FROM dba_sys_privs WHERE grantee = 'APP_USER';

2.3 角色管理

-- 创建应用角色
CREATE ROLE app_read_role;
CREATE ROLE app_write_role;

-- 配置角色权限
GRANT SELECT ON scott.emp TO app_read_role;
GRANT SELECT ON scott.dept TO app_read_role;
GRANT INSERT, UPDATE, DELETE ON scott.emp TO app_write_role;

-- 分配角色给用户
GRANT app_read_role TO app_user;
GRANT app_write_role TO app_admin;

-- 查看角色权限
SELECT * FROM dba_sys_privs WHERE grantee IN ('APP_READ_ROLE', 'APP_WRITE_ROLE');

三、网络访问安全

3.1 配置SSL/TLS加密

# 生成Oracle Wallet(证书存储)
mkdir -p /u01/app/oracle/wallet
orapki wallet create -wallet /u01/app/oracle/wallet -pwd "WalletPass123!" -auto_login_local

# 创建自签名证书
orapki wallet add -wallet /u01/app/oracle/wallet -dn "CN=dbserver.example.com" -keysize 2048 -validity 365 -self_signed -pwd "WalletPass123!"

# 导出证书
orapki wallet export -wallet /u01/app/oracle/wallet -dn "CN=dbserver.example.com" -cert /tmp/dbserver_cert.txt -pwd "WalletPass123!"
-- 配置SQLNet加密
-- 编辑 $ORACLE_HOME/network/admin/sqlnet.ora
ALTER SYSTEM SET sqlnet.encryption_server = REQUIRED SCOPE = BOTH;
ALTER SYSTEM SET sqlnet.encryption_types_server = (AES256, AES192, AES128) SCOPE = BOTH;
ALTER SYSTEM SET sqlnet.crypto_checksum_server = REQUIRED SCOPE = BOTH;
ALTER SYSTEM SET sqlnet.crypto_checksum_types_server = (SHA256, SHA1) SCOPE = BOTH;

3.2 防火墙配置

# 只允许特定IP访问Oracle端口
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="1521" accept'

# 拒绝其他所有访问
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port protocol="tcp" port="1521" drop'

# 重载防火墙规则
firewall-cmd --reload

# 查看规则
firewall-cmd --list-rich-rules

3.3 监听器安全配置

# 编辑 $ORACLE_HOME/network/admin/listener.ora
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dbserver.example.com)(PORT = 1521))
    )
  )

# 安全设置
ADMIN_RESTRICT_LISTENER = ON
SECURE_REGISTER_listener = (TCP)

# 重启监听器
lsnrctl stop
lsnrctl start
lsnrctl reload

四、SQL注入防护

4.1 参数化查询

-- 错误写法(容易SQL注入)
-- SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

-- 正确写法:使用绑定变量
SELECT * FROM users WHERE username = :username AND password = :password;

4.2 输入验证函数

-- 创建输入验证函数
CREATE OR REPLACE FUNCTION validate_input(
    p_input VARCHAR2
) RETURN VARCHAR2 IS
    v_result VARCHAR2(4000);
BEGIN
    -- 移除危险字符
    v_result := REGEXP_REPLACE(p_input, '(''|;|--|/*|*/|xp_|sp_)', '');
    RETURN v_result;
END validate_input;
/

-- 在存储过程中使用
CREATE OR REPLACE PROCEDURE search_employee(
    p_name IN VARCHAR2,
    p_result OUT SYS_REFCURSOR
) AS
BEGIN
    OPEN p_result FOR
        SELECT * FROM employees 
        WHERE name = validate_input(p_name);
END search_employee;
/

4.3 最小权限运行存储过程

-- 以调用者权限运行(更安全)
CREATE OR REPLACE PROCEDURE search_employee(
    p_name IN VARCHAR2,
    p_result OUT SYS_REFCURSOR
) AUTHID CURRENT_USER IS
BEGIN
    OPEN p_result FOR
        SELECT * FROM employees WHERE name = p_name;
END search_employee;
/

-- 使用 DEFINER vs CURRENT_USER
-- DEFINER:以创建者权限运行(存在风险)
-- AUTHID CURRENT_USER:以调用者权限运行(更安全)

五、审计与监控

5.1 启用审计

-- 启用审计
ALTER SYSTEM SET audit_trail = DB, EXTENDED SCOPE = SPFILE;

-- 审计所有SQL操作
AUDIT ALL BY app_user BY SESSION;
AUDIT SELECT TABLE, INSERT TABLE, UPDATE TABLE, DELETE TABLE BY app_user;

-- 审计失败登录
AUDIT CREATE SESSION WHENEVER NOT SUCCESSFUL;

-- 审计特权操作
AUDIT EXECUTE ON DBMS_CDC_PUBLISH;
AUDIT EXECUTE ON DBMS_FLASHBACK;

5.2 查询审计日志

-- 查看审计记录
SELECT username, 
       timestamp,
       action_name,
       sql_text,
       returncode
FROM dba_audit_trail
WHERE username = 'APP_USER'
ORDER BY timestamp DESC;

-- 统计异常操作
SELECT username, action_name, COUNT(*) 
FROM dba_audit_trail
WHERE timestamp > SYSDATE - 7
GROUP BY username, action_name
HAVING COUNT(*) > 100;

-- 查看失败登录
SELECT username, 
       terminal,
       timestamp,
       returncode
FROM dba_audit_trail
WHERE action_name = 'LOGON'
  AND returncode != 0
ORDER BY timestamp DESC;

5.3 实时监控脚本

#!/bin/bash
# /opt/scripts/monitor_sqlplus.sh
# SQLPlus操作实时监控脚本

# 监控可疑SQL
echo "检查最近1小时的异常查询..."
sqlplus / as sysdba << EOF
SELECT username, COUNT(*) as query_count
FROM v\$session s
JOIN v\$sqltext_with_newlines t ON s.sql_address = t.address
WHERE s.logon_time > SYSDATE - 1/24
GROUP BY username
HAVING COUNT(*) > 50
ORDER BY query_count DESC;
EOF

# 检查活跃会话
echo "检查活跃会话..."
sqlplus / as sysdba << EOF
SELECT s.username, s.program, s.status, s.sid, s.serial#
FROM v\$session s
WHERE s.status = 'ACTIVE'
  AND s.username IS NOT NULL
ORDER BY s.logon_time;
EOF

六、文件与目录安全

6.1 配置文件权限

# 保护Oracle配置文件
chmod 600 $ORACLE_HOME/network/admin/sqlnet.ora
chmod 600 $ORACLE_HOME/network/admin/listener.ora
chmod 600 $ORACLE_HOME/network/admin/tnsnames.ora
chown oracle:oinstall $ORACLE_HOME/network/admin/*.ora

# 保护数据文件
chmod 600 /u01/app/oracle/oradata/*.dbf
chown oracle:oinstall /u01/app/oracle/oradata/*.dbf

# 保护备份文件
chmod 600 /backup/oracle/*.dmp
chown oracle:oinstall /backup/oracle/*.dmp

6.2 日志文件保护

# 压缩并加密审计日志
find /u01/app/oracle/admin/orcl/adump -name "*.aud" -mtime +30 -exec gzip {} \;

# 设置日志保留期限
find /u01/app/oracle/admin/orcl/adump -name "*.aud.gz" -mtime +180 -delete

# 保护alert日志
chmod 640 $ORACLE_HOME/diag/rdbms/orcl/orcl/trace/alert_orcl.log

6.3 环境变量安全

# 禁止在命令行中明文显示密码
# 使用Oracle Wallet替代密码
mkstore -wrl /u01/app/oracle/wallet -create
mkstore -wrl /u01/app/oracle/wallet -createCredential ORCL scott "Sc0ttP@ss!"

# 在sqlnet.ora中配置Wallet
WALLET_LOCATION = (SOURCE = (METHOD = FILE)(METHOD_DATA = (DIRECTORY = /u01/app/oracle/wallet)))
SQLNET.WALLET_OVERRIDE = TRUE

# 使用Wallet连接(无需明文密码)
sqlplus /@ORCL

七、高级安全配置

7.1 Oracle Database Vault

-- 启用Database Vault(需单独安装)
EXEC DBMS_MACADM.ENABLE_DATABASE_VAULT;

-- 创建安全区域
BEGIN
  DBMS_MACADM.CREATE_REALM(
    realm_name     => 'HR Data Realm',
    description     => 'Protect HR sensitive data',
    enabled         => DBMS_MACUTL.G_YES,
    audit_options   => DBMS_MACUTL.G_REALM_AUDIT_FAIL);
END;
/

-- 添加保护对象到区域
BEGIN
  DBMS_MACADM.ADD_OBJECT_TO_REALM(
    realm_name => 'HR Data Realm',
    object_type => 'TABLE',
    object_owner => 'HR',
    object_name => 'EMPLOYEES');
END;
/

-- 创建命令规则
BEGIN
  DBMS_MACADM.CREATE_COMMAND_RULE(
    command     => 'DROP TABLE',
    rule_set_name => 'Deploy Table',
    object_owner => '%',
    object_name  => '%');
END;
/

7.2 数据脱敏

-- 创建数据脱敏策略
BEGIN
  DBMS_REDACT.ADD_POLICY(
    object_schema  => 'HR',
    object_name    => 'EMPLOYEES',
    column_name    => 'SALARY',
    policy_name    => 'MASK_SALARY',
    function_type  => DBMS_REDACT.FULL,
    expression     => 'SYS_CONTEXT(''USERENV'',''SESSION_USER'') NOT IN (''HR_ADMIN'')');
END;
/

-- 验证脱敏效果
-- 以普通用户查看(看到的是脱敏数据)
SELECT first_name, last_name, salary FROM hr.employees;
-- 以管理员查看(看到真实数据)
SELECT first_name, last_name, salary FROM hr.employees WHERE SYS_CONTEXT('USERENV','SESSION_USER') = 'HR_ADMIN';

7.3 Transparent Data Encryption (TDE)

-- 创建钱包
ALTER SYSTEM SET ENCRYPTION WALLET OPEN IDENTIFIED BY "WalletPass123!";

-- 创建加密表空间
CREATE TABLESPACE encrypted_ts 
    DATAFILE '/u01/app/oracle/oradata/encrypted_ts01.dbf' 
    SIZE 100M ENCRYPTION USING 'AES256'
    DEFAULT STORAGE (ENCRYPT);

-- 在加密表空间中创建表(数据自动加密)
CREATE TABLE sensitive_data (
    id NUMBER,
    data VARCHAR2(4000)
) TABLESPACE encrypted_ts;

-- 加密现有列
ALTER TABLE hr.employees ADD (salary_encrypted VARCHAR2(4000) ENCRYPT);
UPDATE hr.employees SET salary_encrypted = salary;
ALTER TABLE hr.employees DROP COLUMN salary;
ALTER TABLE hr.employees RENAME COLUMN salary_encrypted TO salary;

八、安全检查清单

8.1 账户安全检查

检查项 检查方法 标准
密码复杂度 检查dba_profiles FAILED_LOGIN_ATTEMPTS >= 3
默认账户 检查dba_users 无EXPIRED状态的默认账户
最小权限 检查dba_sys_privs 无过度授权的DBA
角色分离 检查角色成员 无用户同时拥有读写权限

8.2 网络安全检查

检查项 检查方法 标准
加密通信 检查sqlnet.ora encryption_server = REQUIRED
防火墙 检查firewall-cmd 只开放必要端口
监听器安全 检查listener.ora ADMIN_RESTRICT_LISTENER = ON

8.3 审计检查

检查项 检查方法 标准
审计启用 检查audit_trail audit_trail = DB, EXTENDED
日志保留 检查adump目录 日志保留至少90天
异常告警 检查监控脚本 有自动告警机制

九、常见问题与解决方案

Q1:用户密码过期怎么办?

A

-- 查看密码过期用户
SELECT username, expiry_date FROM dba_users WHERE expiry_date < SYSDATE;

-- 重置密码
ALTER USER scott IDENTIFIED BY "NewStr0ngP@ss!";

-- 设置为不过期
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;

Q2:如何防止SQL注入?

A
1. 使用参数化查询,禁止拼接SQL
2. 启用Oracle Audit Vault监控可疑查询
3. 定期扫描代码中的SQL注入漏洞

Q3:审计日志占用大量空间?

A

-- 启用统一审计日志压缩
BEGIN
  DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_PROPERTY(
    DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    DBMS_AUDIT_MGMT.AUDIT_TRAIL_PROPERTY_RETENTION,
    90);  -- 保留90天
END;
/

-- 清理旧审计记录
BEGIN
  DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
    audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    use_last_arch_timestamp => TRUE);
END;
/

Q4:如何审计SELECT操作?

A

-- 启用细粒度审计(FGA)审计SELECT
BEGIN
  DBMS_FGA.ADD_POLICY(
    object_schema   => 'HR',
    object_name     => 'EMPLOYEES',
    policy_name     => 'AUDIT_EMP_SELECT',
    audit_condition => NULL,
    statement_types => 'SELECT');
END;
/

-- 查询FGA审计记录
SELECT timestamp, db_user, object_schema, object_name, sql_text
FROM dba_fga_audit_trail
WHERE object_name = 'EMPLOYEES';

十、总结

在CentOS上配置SQLPlus安全需要从多个维度入手:

  1. 账户安全:强密码、最小权限、角色分离
  2. 网络安全:SSL/TLS加密、防火墙、监听器加固
  3. SQL注入防护:参数化查询、输入验证、权限控制
  4. 审计监控:启用审计、实时监控、异常告警
  5. 文件安全:配置文件保护、日志加密、环境变量隐藏
  6. 高级安全:Database Vault、数据脱敏、TDE加密

核心要点
– 遵循最小权限原则,避免过度授权
– 使用SSL/TLS加密所有网络通信
– 始终使用参数化查询,防止SQL注入
– 启用审计并定期检查异常操作
– 定期更新安全策略,应对新型威胁

通过本文的指南,你可以建立完善的SQLPlus安全防护体系,确保Oracle数据库在CentOS环境中的安全运行。

注:本文基于CentOS 7/8和Oracle 19c/21c编写,具体配置可能因版本差异而略有不同。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注