Oracle如何找到引起賬號鎖定的IP的一點思考與總結
本文轉載自微信公眾號「DBA閑思雜想錄」,作者瀟湘隱者。轉載本文請聯系DBA閑思雜想錄公眾號。
在ORACLE數據庫中,如果沒有修改過FAILED_LOGIN_ATTEMPTS的話,默認10次輸入錯誤密碼后就會鎖住用戶。
- SQL> SELECT *
- 2 FROM DBA_PROFILES
- 3 WHERE RESOURCE_NAME='FAILED_LOGIN_ATTEMPTS';
- PROFILE RESOURCE_NAME RESOURCE LIMIT
- ------------------------------ -------------------------------- -------- ----------------------------------------
- DEFAULT FAILED_LOGIN_ATTEMPTS PASSWORD 10
- MONITORING_PROFILE FAILED_LOGIN_ATTEMPTS PASSWORD UNLIMITED
- SQL>
那么在數據庫維護過程中,如果出現賬號被鎖定的情況,如何事后分析是那個IP或主機導致賬號被鎖定了呢?不同的情形有不同的分析方法,主要看是否開啟了數據庫審計功能
開啟了數據庫審計
如果開了審計功能的話,這個分析定位就非常簡單容易。因為數據庫的審計功能會記錄這些信息到數據庫當中。
檢查是否開啟審計,主要查看audit_sys_operations參數是否為TRUE。
- SQL> show parameter audit
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- audit_file_dest string /u01/app/oracle/admin/gsp/adum
- p
- audit_sys_operations boolean TRUE
- audit_syslog_level string
- audit_trail string DB_EXTENDED
- SQL>
如果開啟了審計功能,通過下面SQL語句就能輕松找到引起賬號鎖定的主機(通過主機找到具體IP地址)
----RETURNCODE=1017表示登錄失敗返回ORA-01017: invalid username/password; logon denied錯誤的會話信息。
- SELECT USERNAME
- ,USERHOST
- ,TIMESTAMP
- ,RETURNCODE
- FROM dba_audit_session
- WHERE USERNAME='TEST'
- AND RETURNCODE='1017'
- ORDER BY TIMESTAMP DESC;
數據庫審計關閉
如果數據庫審計功能是關閉的情況下,那么能否定位、找到導致賬號鎖定的主機或IP地址呢?如果出現賬號被鎖的情況,可以先查一下dba_users視圖,看看賬號是在什么時間點被鎖定的。注意(有些版本有Bug,會出現LOCK_DATE不準確的情況。)
- SQL> ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';
- Session altered.
- SQL> SELECT username, account_status,lock_date, PROFILE
- 2 FROM dba_users WHERE username='TEST';
- USERNAME ACCOUNT_STATUS LOCK_DATE PROFILE
- ------------------------------ -------------------------------- ------------------- ----------
- TEST LOCKED(TIMED) 2018-06-16 23:49:14 DEFAULT
- SQL>
網上有些文章信誓旦旦的宣稱通過監聽日志可以分析出哪些IP導致賬號被鎖定了,但是經過動手實驗分析,發現通過監聽日志文件根本無法定位引起賬號鎖定的IP地址,原因有兩個:
1、 無法通過監聽日志判斷登錄會話是否出現ORA-01017錯誤,因為登錄成功與登錄失敗遭遇ORA-01017錯誤的會話的監聽日志信息是一樣。無法區別!
2、 即使賬號鎖定的時間能定位到秒,但是生產環境中,一秒內有大量的監聽日志生成,根本無法定位是哪一個具體IP
3、 登錄失敗的監聽日志可能不是連續的。而是在一段時間生成的。
不過如果事前你定義了數據庫觸發器,那么就可以輕松定位到具體IP, 網友提供了一個觸發器,如下所示:
- CREATE OR REPLACE TRIGGER sys.logon_denied_to_alert
- AFTER servererror ON DATABASE
- DECLARE
- message VARCHAR2(168);
- ip VARCHAR2(15);
- v_os_user VARCHAR2(80);
- v_module VARCHAR2(50);
- v_action VARCHAR2(50);
- v_pid VARCHAR2(10);
- v_sid NUMBER;
- v_program VARCHAR2(48);
- v_username VARCHAR2(32);
- BEGIN
- IF (ora_is_servererror(1017)) THEN
- -- get ip FOR remote connections :
- IF upper(sys_context('userenv', 'network_protocol')) = 'TCP' THEN
- ip := sys_context('userenv', 'ip_address');
- END IF;
- SELECT sid INTO v_sid FROM sys.v_$mystat WHERE rownum < 2;
- SELECT p.spid, v.program
- INTO v_pid, v_program
- FROM v$process p, v$session v
- WHERE p.addr = v.paddr
- AND v.sid = v_sid;
- v_os_user := sys_context('userenv', 'os_user');
- v_username := sys_context('userenv','authenticated_identity');
- dbms_application_info.read_module(v_module, v_action);
- message := to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') ||
- ' Password Erro: logon denied from ' || nvl(ip, 'localhost') || ' ' ||
- v_pid || ' User:' || v_os_user || ' with ' || v_program || ' – ' ||
- v_module || ' ' || v_action||' dbuser:' || v_username;
- sys.dbms_system.ksdwrt(2, message);
- END IF;
- END;
- /
在客戶端使用SQL*Plus測試,模擬輸入錯誤的密碼登錄數據庫
- C:\Users>sqlplus test/1234@myvm
- SQL*Plus: Release 11.2.0.1.0 Production on 星期日 6月 17 00:35:21 2018
- Copyright (c) 1982, 2010, Oracle. All rights reserved.
- ERROR:
- ORA-01017: invalid username/password; logon denied
此時,觸發器捕獲到這個錯誤,就會在告警日志中生成類似下面這樣的錯誤日志信息:
- Sun Jun 17 08:01:44 2018
- 2018-06-17 08:01:44 Password Erro: logon denied from 192.168.125.193 26639 User:KongLB with sqlplus.exe ��� sqlplus.exe dbuser:test
當然,如果你也可以改寫該觸發器,將捕獲的相關信息寫入數據庫相關表。目前,我是將登陸失敗的信息寫入告警日志,監控告警日志(alert_$ORACLE_SID.log)的作業則會將分析告警日志,定期將錯誤解析出來,發送給DBA!