Автор: David Litchfield [[email protected]] Дата: 20 апреля 2007 Перевод: Robin_Hood www.antichat.ru Любая организация должна иметь четкий план действий на случай непредвиденных ситуаций, атак.. Для тех же, у кого такого плана нет, спонтанным решением может быть выдернуть провод или отсоединить систему от сети. Это понятная реакция, так как дальнейшее вторжение в этом случае невозможно. Учитывая, что атакующий может поставить под угрозу базу данных Oracle с администраторскими привилегиями, можно создать следующий спусковой механизм: Code: CREATE OR REPLACE TRIGGER VANISH BEFORE SHUTDOWN ON DATABASE BEGIN DELETE FROM SYS.AUD$; END; / Когда база данных выключена правильно, сотрется контрольный журнал, что сделает задание исследователя немного сложнее. Конечно, взломщик может сделать больше, чем стереть все аудиторские следы в таком триггере. Оглядываясь на проблемы выше, а также связанные с потерей временной информации, некоторые организации предпочитают обеспечивать анализ системы, пока она подключена к сети. Этот метод называется живой ответ. Живой ответ безопасно хранит всю временную информацию для дальнейшего анализа, другими словами – вся информация, утерянная в результате отключения машины от сети или выключения будет сохранена. Это дает возможность исследователю собрать информацию в читаемом формате, более удобном чем его сохраненная двоичная копия – к примеру логи. Эта статья затрагивает начальные понятия о живом ответе, но в основном фокусируется на основных аспектах специфики Oracle. Сейчас есть много книг, касающихся живого ответа – лично я могу посоветовать Real Digital Forensics (Addison-Wesley) by Richard Bejtlich, Keith Jones and Curtis Rose Там, где это возможно, исследователь должен брать на себя действия живого ответа, по отношению особы которая близко подобралась к самой системе, по двум причинам. Во-первых, этот человек может действовать как свидетель, который, в случае суда, поможет усилить впечатление правдивости. Во-вторых, эта особа может помочь исследователю совершить какие либо неправомерные действия, как-то создание нового пользователя с правами администратора. До более подробного рассмотрения спецификаций Oracle Live Response, я хочу поговорить про доверие и гарантии этого сервиса. Поскольку он выполняется на уже скомпрометированной системе, можем ли мы ему доверять, точна ли предоставленная информация? Позвольте объяснить на примере. При использовании на Windows сервере, аудитор системы сможет пользоваться всеми средствами на CD. Когда будет вставлен диск и запущена одна из утилит, Windows создаст новый процесс, утилита получит свое адресное пространство, где будет располагать свои dll, т.е. память, которую он использует. Более углубляясь в техническую информацию, командный процессор вызывает CreateProcess(), которая в свою очередь вызывает NTCreateProcess(). Потом ядро создаст объект процесса, выделит память, поместит ntdll.dll в нее. Потом загружается код программы и все используемые DLL. В момент загрузки ntdll.dll в память может быть скомпрометированы доверие и гарантии, при условии, что у нападающего есть полный контроль над системой, в памяти может быть пропатчена ntdll.dll так, что это произведет к полному контролю. Если у нападающего есть полный доступ к системе, он может подделывать результаты ответов. Из-за этого можно подвергнуть сомнению правильность данных Живого Ответа, но есть другая проблема. Из-за легкой изменчивости информации, как только это пошло, это пошло. Это означает, что Живой Ответ не восстанавливаем, и также мог быть сомнителен в суде. Чтобы предотвратить это, исследователь должен полностью документировать все, что он делают в системе в течение действия Живого Ответа и иметь свидетеля, чтобы подтвердить это. Так в чем же состоит преимущество Живого ответа, если результаты могут быть подменены? Ну, во первых, не каждый атакующий может полностью скомпрометировать систему, что будет означать подделку результатов; во вторых secondly, большинство не будет скрывать следы атаки, даже если они и захватили систему; в третьих, информация, полученная из Live Response может быть использована немедленно; в четвертых, если Live Response не предоставляет ни какой подозрительной информации, в то время как различные межсетевые экраны указывают на вторжение в систему – анализ наверняка покажет наличие rootkit технологий. Разобравшись с ответами живого ответа, простите за тавтологию, насколько они надежны и им можно доверять, взглянем на сам Oracle Live Response поближе. Основные шаги Во время Живого Ответа, для аудитора системы невозможно не оставить какого либо следа в системе, но он должен постараться сделать этот след как можно меньше заметным. Практически любые действия повлекут за собой запись в системный журнал. Эти изменения неминуемы, но должны быть ожидаемы как допустимые. Что недопустимо для исследователя – создавать новые файлы через редирект данных от Живого Ответа в файл. Это может перезаписать блоки на диске, которые могут содержать удаленную информацию, используемую бы в результате последующего оффлайн-анализа. Все исходящая информация из Живого Ответа должна быть записана минуя сеть. Есть три способа сделать это: первый – маппингом диска если система запущена под Windows или Samba, потом используя редирект ввода: D:\>listdlls.exe > z:\case-0001-listdlls.txt Использование редиректа может повлечь за собой ошибки, - к примеру, если набрать C вместо Z – это повлечет за собой неприятности. Второй метод направить информацию через сеть, используя netcat или cryptcat. Cryptcat даже предпочтительнее чем netcat из-за шифрования данных. Очевидно, что любое обращение к потоку “stderr” не будет перенаправлено через сеть – только информация с потока “stdout”: D:\>type output.c Code: #include <stdio.h> int main() { fprintf(stdout,"This will be piped/redirected...\n"); fprintf(stderr,"This will not be piped/redirected...\n"); return 0; } D:\>output.exe | nc 192.168.1.100 7777 This will not be piped/redirected... D:\> Если вы используете пайпы или редирект, важно будет точно записать любые ошибки, направленные на консоль через поток “stderr”. Альтернатива этим двум методам – установить утилиту, работающею прямо через сеть - к примеру, WebJob от KoreLogic. Сервером может быть даже лэптоп, но исследователь должен быть уверен в наличии свободного пространства для информации в несколько гигабайт. Специфика Живого Ответа должна быть проведена и основные шаги должны быть усвоены сейчас. Они включают в себя следующую информацию. Системное время и дата Исследователь в первую очередь должен выяснить системное время и дату. Залогиненые пользователи Список пользователей, находящихся в системе, а так же информация о том, сколько времени они провели, действительно полезна Список всех пользователей и групп Включает в себя список всех пользователей, группы и членство в них а так же дата последнего входа пользователей. Список открытых портов и соединений До углубления этот вопрос, давайте рассмотрим следующее: Вы отключаете систему от сети или нет. Если так, с какими версиями Windows активное соединение будет сброшено, а информация удалится. Если же не отключать систему от сети, и взломщик до сих пор онлайн, у него больше шансов нанести вред системе. С другой стороны, это позволяет исследователю собрать больше информации о атаке. Ответ на вопрос о отключении или нет должен быть взвешен и тщательно рассмотрен до атаки. Все TCP- и UDP- порты должны быть под контролем, это позволит узнать как нападающий получил контроль над системой. Обращайте внимание на соединения с сервером. В зависимости от того, запущен сервер в shared mode или нет, определит, будет ли клиент коннектится к 1521(подразумевается, что это порт Oracle), или к случайным портам. Другой признак осмотреться – это множество портов, отсылающие SYN пакеты. Это показатель TCP сканирования с хоста исследования. Список запущенных процессов Должен быть получен полный список запущенных процессов. Особое внимание стоит уделять шеллам вроде cmd.exe или /bin/sh, не следует спускать глаз с for //bin/sh. Исследователь также должен получить список родительских процессов. В случае, если родительский процесс уже завершен, будет сложнее, но исследование над открытыми хендлами может помочь. Список DLL Список DLL или объектов, загружаемых каждым процессом также должен быть получен. Держите ухо востро с старыми именами; Windows смотрит за DLL, загруженными с использованием UNC через сеть. Список открытых хендлов Так же важен список, какой процесс какие хендлы открыл. С этим списком можно воспроизвести действия атакующего, идентифицировать родительские процессы. Дампы памяти Дампы памяти всех запущенных процессов должны быть собраны для «нормального» просмотра. Ведь атакующий может запустить процесс вроде “notepad”, и используя CreateRemoteThread() загрузить свой код внутрь адресного пространства. Также обязателен дамп реестра. Сделайте копии всех логов Все серверные логии должны быть скопированы для последующего анализа. Файлы Oracle Логии, контрольные файлы Oracle могут находиться в различных местах, поэтому узнаем, как их побыстрее найти. Сначала нужно узнать где установлен каждый экземпляр Oracle. В реестре, HKEY_LOCAL_MACHINE\Software\Oracle Registry содержит информацию о каждом. Для каждого экземпляра должен быть выделен загрузочный файл. Его можно найти в “database” (Windows), или “dbs” - *nix. Стандартное имя файла “spfilesid.ora”, где “sid” – сервисный идентификатор базы данных. Этот файл содержит информацию о местонахождении логов. audit_file_dest background_dump_dest core_dump_dest db_recovery_file_dest user_dump_dest utl_file_dir control_files db_create_file_dest db_create_online_log_dest_n log_archive_dest log_archive_dest_n Исследователь должен брать во внимание, что список, приведенный выше может отличатся от настроек, используемых Oracle, - к примеру если взломщик использует “ALTER SYSTEM” или “ALTER DATABASE”. Позже мы поговорим о получении этой информации, а сейчас рассмотрим данные директории. Audit_file_dest Если аудит включен и сконфигурирован на логирование файлов операционной системы, файлы аудита будут расположены в это директории. Background_dump_dest Содержит alert.log и маршрутные файлы. Core_dump_dest Дампы сервера содержатся в этой папке. Файлы могут обозначать сигнал о переполнении. Db_recovery_file_dest Папка flash востановлени, содержит логии отката. User_dump_dest Информация о процессах пользователя записана в эту директорию. Utl_file_dir Используется для PL/SQL файлов I/O – к примеру, во время использования UTL_FILE. Control_files Содержит список контрольных файлов используемых сервром. Они, в свою очередь, содержат информацию о дата файлах. Db_create_file_dest Эта директория для дата файлов Oracle. Она опциональна, и может содержать в себе журналы отката и контрольные файлы, если db_create_online_log_dest_n не установлена. Db_create_online_log_dest_n Используется, если логи отката не обнаружены.n должна быть заменена цифрой, начинающейся на 1. Опять же таки, опционально. Log_archive_dest, log_archive_dest_n и log_archive_duplex_dest Могут использоваться для заархивированных логов отката. Oracle Data Files Контрольные файлы содержат расположение дата файлов, но здесь есть потенциальная опасность. Сервер пожжет содержать много терабайтов, иногда даже петабайт или два дата файлов, и невозможно хранить их на сервере. Однако, возможно копировать ключ дата файлов. Это те файлы, в имени которых содержится SYSTEM, SYSAUX, TEMP иUNDO. Все должно быть скопировано на сервер. Внешние файлы. Oracle может записывать файлы в файловую систему используя Java и UTL_FILE PL/SQL. Параметр UTL_FILE_DIR указывает, откуда Oracle может читать файлы и куда писать. Файлы могут быть собраны для анализа. Если входящие файлы – астериксы, Oracle может записать их в любое место в файловой системе. Мы также будем коротко обсуждать внешние таблицы. Прослушивающие логии Их можно найти в ORACLE_HOME/network/log directory by default.. Если файл не существует, файлы могут находится в ORACLE_HOME/network/admin/listener.ora. Какпредупреждение, местонахождение в этом файле может быть не «живым». К примеру, в Oracle 9 и ранних версиях, если пароль не был установлен, взломщик мог модифицировать местонахождение логов. Команда the «lsnrctl Status» покажет статус входа в лог файл: C:\oracle\product\10.2.0\db_1\BIN>lsnrctl status LSNRCTL for 32-bit Windows: Version 10.2.0.2.0 - Production on 06- APR-2007 01:28:18 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for 32-bit Windows: Version 10.2.0.2.0 - Production Start Date 06-APR-2007 01:27:36 Uptime 0 days 0 hr. 0 min. 41 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File C:\oracle\product\10.2.0\db_1\network\admin\listener.ora Listener Log File c:\temp\listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1ipc))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=APOLLO)(PORT=1521))) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully C:\oracle\product\10.2.0\db_1\BIN> Мы можем увидеть расположение логов - C:\temp\listener.log. «Статус» будет выглядеть dtplt одинаково: 06-APR-2007 01:30:04 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=)(USER=david))(COMMAND=status)(ARG UMENTS=64)(SERVICE=LISTENER)(VERSION=169869824)) * status * 0 Также, видно записанное время, поэтому перед командой “lsnrctl status” узнайте время. Запросы к серверу используя SQLPlus Исследователь должен соединится с сервером с привилегиями SYS, если это возможно. Это позволит получить доступ к информации, необходимой для исследования. После этого, не нужно предпринимать никак действий чтобы поменять базу данных. К примеру, нельзя исполнять все DML операции, такие как , INSERT, UPDATE или DELETE; нельзя создавать обьекты – даже временные глобальные таблицы; нельзя выполнять операции GRANT или REVOKE с привилегиями; нельзя использовать ALTER – особенно чтобы делать дампы лог файлов или дата файлов. Знайте, что несмотря на эти предупреждения, всего лишь факт соединения с сервером может изменить их: "устанавливающийся" вход может быть создан в прослушивающем лог файле; может быть вставлена информация в контрольные журналы (AUD$) либо файлы аудита – если соединение не SYS. Когда исполнится SQL, это в корне изменит информацию во многих журналах вроде V$SQL. Вот почему соединение с RDBMS должно быть последним предпринятым исследователем. Предположим, что исследователь будет использовать sqlplus для соединения с сервером. До соединения, нужно проверить следующие файлы, дабы убедится, что они не содержат никакого SQL кода, выполняющих следующие операции: $ORACLE_HOME/bin/LOGIN.SQL $ORACLE_HOME/dbs/LOGIN.SQL $ORACLE_HOME/SQLPlus/admin/glogin.sql Еще одно предупреждение – помните проблемы с доверием? Мы не можем обязательно доверять системе, на которой запущен Живой Ответ, это даже более полезно, когда данные идут непосредственно напрямую. Возможно, атакующий еще не получил root привилегии в системе, достаточно тривиально получить DBA во время, когда система запущена. Для того чтобы скрывать свое прибивание в системе, взломщик может модифицировать логии, к примеру, он мог модифицировать DBA_ROLE_PRIVS, скрывая факт администраторских привилегий: SQL> SELECT GRANTEE FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = 'DBA'; GRANTEE ---------------------------- SYS SYSMAN SYSTEM Однако, это будет заметно в запросе к основным таблицам: SQL> SELECT U.NAME FROM SYS.USER$ U, SYS.SYSAUTH$ A WHERE U.USER# = A.GRANTEE# AND PRIVILEGE# = (SELECT USER# FROM SYS.USER$ WHERE NAME = 'DBA'); NAME ------------------------------ SYS HACK101 SYSTEM SYSMAN Во время работы sqlplus и до соединения с сервером, все запросы и результаты жолжны быть записано в файл, это может быть достигнуто командой SPOOL, сопровождаемой именем файла. Имя файла должно быть «значащим» - к примеру, должно содержать номер исследования, дату и время: C:\oracle\product\10.2.0\db_1\BIN>TIME The current time is: 6:12:22.93 Enter the new time: C:\oracle\product\10.2.0\db_1\BIN>DATE The current date is: 27/03/2007 Enter the new date: (dd-mm-yy) C:\oracle\product\10.2.0\db_1\BIN>SQLPLUS /NOLOG SQL*Plus: Release 10.2.0.2.0 - Production on Tue Mar 27 06:12:29 2007 Copyright (c) 1982, 2005, Oracle. All Rights Reserved. SQL> SPOOL C:\IR-CASES\N0017\SQL-CASE-N0017-27-03-2007-06-12-22.TXT Соединение должно осуществляется с лэптопа через сеть, включать в себя IP исследуемого сервера, номер порта и идентификатор базы данных(SID). SQL> CONNECT SYS/[email protected]:1521/ORCL AS SYSDBA Connected. SQL> После соединения нужно изменить сессию, задать формат даты, включая минуты, часы, секунды, иначе данные из колонок типа DATE появятся как «ДЕНЬ-МЕСЯЦ-ГОД», к примеру «16-МАР-07». SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; Узнаем прежде выполненный SQL код При соединении с сервером, первый запрос, выполненный исследователем должен быть тот, который отобразит последние выполненные запросы. В Oracle 10g запрос будет следующий: SQL> SELECT LAST_ACTIVE_TIME, PARSING_USER_ID, SQL_TEXT FROM V$SQL ORDER BY LAST_ACTIVE_TIME ASC; Это покажет кто и когда исполнял какие команды из списка V$SQL. Есть ограниченное число записей, около 2500, и это является круглым - то есть старшие записи переписуются с новыми записями. Если исследователь может получить эту информацию как можно быстрее после того, как инцидент замечен тогда есть шанс, что все еще будет подарок свидетельства. На нагруженном сервере, конечно, понижены возможности, но вопрос должен все еще выполняться. Если есть содержание ценности к исследованию тогда пользовательский id и время, в которое был SQL, выполняют, оба доступны. Должно быть отмечено, что эта информация должна также быть доступной в дампах памяти, выполненных ранее.
В Oracle 9i нет колонки LAST_ACTIVE_TIME, поэтому запрос нужно слегка изменить: SQL> SELECT PARSING_USER_ID, SQL_TEXT FROM V$SQL ORDER BY PARSING_USER_ID ASC; В 10g таблицы Automatic Workload Repository History WRH$_SQLTEXT и WRH$_SQLSTAT могут также содержать факты и поэтому должны быть запрошены: SQL> SET LONG 2000000000 SQL> SELECT ST.PARSING_SCHEMA_ID, TX.SQL_TEXT FROM WRH$_SQLSTAT ST, WRH$_SQLTEXT TX WHERE TX.SNAP_ID = ST.SNAP_ID; Строка, содержащая “SET LONG 2000000000” сообщает sqlplus показать 2000000000 символов для SQL_TEXT поскольку это будет обрезано иначе имеющий тип CLOB. Эта таблица содержит обширное количество предыдущих SQL запросов, а также очень высоковероятно, что она содержит множество точных фактов о точ, что есть нужные доказательства.Она содержит SELECT, UPDATE, INSERT, DELETE, возможно ALTER, то есть запросы, отнимающие много времени на выполнение. Это один из случаев, когда исследователь должен быть в состоянии найти некоторые SELECT – запросы в отсутствие аудита. Как только данные извлечены из таблицы, они должны быть «безопасны» move onto to другие запросы. «Безопасны» взято в кавычки потому что как только новые запросы выполнены, они поместят в SQL_TEXT записи от предыдущих выполненных запросов. Вот почему мы подвергли их сомнению. Следующей строчкой должен быть лог аудита. Все должно быть извлечено из таблицы для последующего изучения и анализа. SQL> SELECT * FROM AUD$; Если аудит-информация подключена к серверу или к системному демону, она должна быть собрана до подключения и запросов к серверу. Сбор информации о входах – текущих и прежних Пока таблица AUD$ будет содержать информацию о входах, обеспечивая аудит, и подключена к серверу, можно получить свидетельства входов везде. Фиксированный просмотр V$ACTIVE_SESSION_HISTORY использует циркулирующий буфер в SGA для размещения, взятую каждую секунду, об активных сессиях. Эти сессии протекают от SGA в таблицу WRH$_ACTIVE_SESSION_HISTORY, часто, как часть Automatic Workload Repository. Это важные данные, так как содержат информацию о всех входах в систему. SQL> SELECT USER_ID, SESSION_ID, SAMPLE_TIME FROM SYS.WRH$_ACTIVE_SESSION_HISTORY Исследователь должен получить список пользователь, присутствующих на сервере в данный момент: SQL> SELECT SID, USER#, USERNAME, TERMINAL, OSUSER, PROGRAM, LOGON_TIME FROM V$SESSION; Также важно получить список всех пользователей системы. SQL> SELECT USER#, NAME, ASTATUS, PASSWORD, CTIME, PTIME, LTIME FROM SYS.USER$ WHERE TYPE#=1; Должен быть выбран хеш пароля, чтобы показать, насколько пароль стойкий для подбора взломщиком. ASTATUS покажет, заблокирован аккаунт или нет, если да, LTIME покажет когда; CTIME покажет дату создания, а PTIME – время последней смены пароля. Список roles также важен SQL> SELECT USER#, NAME, PASSWORD, CTIME, PTIME FROM SYS.USER$ WHERE TYPE#=0; Получение списка roles memberships SQL> SELECT U.NAME AS "GRANTEE", U2.NAME AS "ROLE" FROM SYS.USER$ U, SYS.USER$ U2, SYS.SYSAUTH$ A WHERE U.USER# = A.GRANTEE# AND PRIVILEGE# = U2.USER#; Получение списка привилегий объекта Будет важно получить список всех привилегированных объектов, чтобы просмотреть, нет ли там чего нибуть подозрительного. SQL> SELECT U.NAME AS "GRANTEE", P.NAME AS "PRIVILEGE", U2.NAME AS "OWNER", O.NAME AS "OBJECT" FROM SYS.USER$ U, SYS.USER$ U2, SYS.TABLE_PRIVILEGE_MAP P, SYS.OBJ$ O, SYS.OBJAUTH$ A WHERE U.USER# = A.GRANTEE# AND A.OBJ# = O.OBJ# AND P.PRIVILEGE = A.PRIVILEGE# AND O.OWNER#=U2.USER#; Точно такиеже действия для системных привилегий: SQL> SELECT U.NAME AS "GRANTEE", S.NAME AS "PRIVILEGE" FROM SYS.USER$ U, SYS.SYSAUTH$ A, SYS.SYSTEM_PRIVILEGE_MAP S WHERE U.USER# = A.GRANTEE# AND PRIVILEGE# = S.PRIVILEGE ORDER BY U.NAME; Исследователь должен получить список всех объектов, включая их ID, хозяина, имя, время создания и модификации, время спецификации. SQL> SELECT OBJ#, OWNER#, NAME, TYPE#, CTIME, MTIME, STIME FROM SYS.OBJ$ ORDER BY CTIME ASC; Получение списка удаленных таблиц В 10g, если пользователь удалил любые таблицы, не убрав их при этом из Корзины, они будут доступны: SQL> SELECT U.NAME, R.ORIGINAL_NAME, R.OBJ#, R.DROPTIME, R.DROPSCN FROM SYS.RECYCLEBIN$ R, SYS.USER$ U WHERE R.OWNER#=U.USER#; Получение списка блоковых изменений Каждый файл поделен на блоки, каждый блок содержит информацию о времени изменения, к примеру, после COMMIT. Она содержится в SCN. Когда столбики изменяются, обновляется SCN, что означает, что все другие столбики в блоке отражают тот же самый SCN. Это важное открытие для исследований. Вот пример запроса и отрывок результата: SQL> SELECT O.ORA_ROWSCN, O.CTIME, O.MTIME, O.STIME, U.NAME, O.NAME FROM SYS.OBJ$ O, SYS.USER$ U WHERE U.USER#=O.OWNER# ORDER BY 1; … … 2282280 05-APR-07 06-APR-07 05-APR-07 SYS WRH$_SERVICE_WAIT_CLASS 2282280 05-APR-07 05-APR-07 05-APR-07 SYS WRH$_SERVICE_WAIT_CLASS_PK 2282280 05-APR-07 05-APR-07 05-APR-07 SYS P_TEST 2282280 05-APR-07 05-APR-07 05-APR-07 SYS VP_TEST 2282280 05-APR-07 05-APR-07 05-APR-07 SYS P_TEST 2282280 05-APR-07 05-APR-07 05-APR-07 SYS VANISH 2282280 05-APR-07 09-APR-07 09-APR-07 SYS X 2282280 05-APR-07 06-APR-07 05-APR-07 SYS WRH$_SQLSTAT 2282280 05-APR-07 06-APR-07 05-APR-07 SYS WRH$_SYSTEM_EVENT … … Если преобразовать SCN в отпечаток времени, можно увидеть изменения 9 Апреля: SQL> SELECT SYS.SCN_TO_TIMESTAMP(2282280) FROM DUAL; SYS.SCN_TO_TIMESTAMP(2282280) ------------------------------------------------------------ 09-APR-07 14.39.56.000000000 Смотря на результат предыдущего запроса, можно увидеть, что объект с именем X имеет MTIME и STIME установленные на эту, и это - единственный объект, который соответствует. Таким образом, можно увидеть, что SCN для всех других обьектов(чтение столбиков) в одном блоке разделяют один SCN даже если они не были модифицированы. Вот другой пример: SQL> SELECT U.ORA_ROWSCN, U.NAME FROM SYS.USER$ U WHERE TYPE#=1 ORDER BY 1; ORA_ROWSCN NAME ---------- ------------------------------ 537106 EXFSYS 537106 DMSYS 537106 TSMSYS 537106 DBSNMP 537106 ANONYMOUS 537106 XDB 537106 CTXSYS 537106 WMSYS 1465169 OUTLN 1465169 DIP 1465169 SYS 1465169 SYSTEM 2277427 MARK_POINT2 2277427 PWDTEST 2277427 MARK_POINT 2277427 FINDME_TOO 2277427 FINDME 2277427 SCOTT 2277427 MGMT_VIEW 2277427 MDDATA 2277427 SYSMAN 2277427 MDSYS 2277427 SI_INFORMTN_SCHEMA 2277427 ORDPLUGINS 2277427 TESTUSER 2277427 OLAPSYS 2277427 ORDSYS 27 rows selected. Пользователи MARK_POINT2, PWDTEST, MARK_POINT, FINDME_TOO, FINDME, SCOTT, MGMT_VIEW, MDDATA, SYSMAN, MDSYS, SI_INFORMTN_SCHEMA, ORDPLUGINS, TESTUSER, OLAPSYS и ORDSYS существуют в одном блоке, и разделяют один SCN . Ели мы изменим пароль SCOTTа, SCN зафиксирует изменения для всех пользователей: SQL> ALTER USER SCOTT IDENTIFIED BY PASSWORD; User altered. SQL> SELECT U.ORA_ROWSCN, U.NAME FROM SYS.USER$ U WHERE TYPE#=1 ORDER BY 1; ORA_ROWSCN NAME ---------- ------------------------------ 537106 EXFSYS 537106 DMSYS 537106 TSMSYS 537106 DBSNMP 537106 ANONYMOUS 537106 XDB 537106 CTXSYS 537106 WMSYS 1465169 OUTLN 1465169 DIP 1465169 SYS 1465169 SYSTEM 2283062 MARK_POINT2 2283062 PWDTEST 2283062 MARK_POINT 2283062 FINDME_TOO 2283062 FINDME 2283062 SCOTT 2283062 MGMT_VIEW 2283062 MDDATA 2283062 SYSMAN 2283062 MDSYS 2283062 SI_INFORMTN_SCHEMA 2283062 ORDPLUGINS 2283062 TESTUSER 2283062 OLAPSYS 2283062 ORDSYS 27 rows selected. Поскольку SCN зафиксировал изменения всего блока, можно сделать вывод, что он не укажет вам иголку в стоге сена, но уменьшит объем работы. Получение версии сервера и уровень пропатчености Этот запрос вернет основную и вторичную версию сервера: SQL> SELECT BANNER FROM V$VERSION; Однако это не покажет, насколько пропатчен сервер. Вместо этого, могут быть взяты контрольные суммы для каждой PL/SQL сборки на сервере и сравнить их с имеющимися. Это позволит узнать, какие сборки были модифицированы: Code: SQL> SET NUMF 999999999999999999999999999999 SQL> DECLARE TYPE C_TYPE IS REF CURSOR; CV C_TYPE; V_ONAME VARCHAR2(30); V_OWNER VARCHAR2(30); V_OBJID NUMBER; V_HASH NUMBER; BEGIN DBMS_OUTPUT.ENABLE(100000); OPEN CV FOR 'SELECT U.NAME,O.NAME,O.OBJ# FROM SYS.OBJ$ O, SYS.USER$ U WHERE O.OWNER#=U.USER# AND O.TYPE# = 11 ORDER BY U.NAME'; LOOP FETCH CV INTO V_OWNER,V_ONAME,V_OBJID; EXECUTE IMMEDIATE 'SELECT SUM(SYS.DBMS_UTILITY.GET_HASH_VALUE (SOURCE,1,1073741824)) FROM SYS.SOURCE$ WHERE OBJ# = :1' INTO V_HASH USING V_OBJID; DBMS_OUTPUT.PUT_LINE(V_OWNER||'.'||V_ONAME||':'||V_HASH); EXIT WHEN CV%NOTFOUND; END LOOP; CLOSE CV; END; / Ответ будет следующим: … … SYS.DBMS_PICKLER:235688071 SYS.DBMS_JAVA_TEST:821262485 SYS.UTL_FILE:992849395 SYS.UTL_RAW:407384329 SYS.UTL_TCP:308711346 … … Здесь номер после хозяина и сборек – хеш. Этот хеш был создан используя сумму хеша каждой строчки кода, зашифрованной функцией DBMS_UTILITY.GET_HASH_VALUE. Эти хеши также могут быть сравнены с списком известных хешей. Примите к сведению, что в скомпрометированной системе взломщик может изменить сборку DBMS_UTILITY или любой Другой обьект включая функции памяти С. Параметры сервера Не достаточно всего лишь получить копию файла параметра загрузки сервера. Причина проста – файл параметра содержит настройки для первого запуска сервера. После этого настройки могут быть изменены с помощью команды «ALTER SYSTEM». SQL> SELECT NAME,VALUE FROM V$PARAMETER Любая разница между файлом загрузки и «живыми» параметрами должна быть узнана. Также есть некоторое количество скрытых параметров. Они могут быть уточнены следующим запросом: SQL> select n.ksppinm as "NAME", v.ksppstvl as "VALUE" from sys.x$ksppi n, sys.x$ksppcv v where n.inst_id=userenv('Instance') and v.inst_id=n.inst_id and n.indx=v.indx and substr(n.ksppinm,1,1)='_'; Получение всех параметров, в том числе и скрытых, в том же запросе может быть получено через удаление “and substr(n.ksppinm,1,1)='_'” из запроса выше. Собирая внешние файлы, исследователь также может «открыть» новые места нахождения дампов из запроса выше, и любой файл, существующий в данных директориях, также должен быть скопирован на сервер
Список всех дата файлов Как уже обсуждалось, имена дата файлов, создаваемых SYSTEM, SYSAUX, TEMP и UNDO могут быть получены из контрольных файлов. Следующий запрос может быть применен, если любого из них не хватает SQL> SELECT T.NAME AS "TABLESPACE", D.NAME AS "FILNAME" FROM V$DATAFILE D, TS$ T WHERE T.TS#=D.TS#; Любой файл, выведенный как часть tablespaces должен быть скопирован на сервер. Список всех директорий Директории используются Oracle для внешнего доступа к файлам. Запрос, указанный ниже покажет путь к файлу в данных директориях: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "DIRECTORY", D.OS_PATH AS "PATH" FROM SYS.OBJ$ O, SYS.USER$ U, SYS.DIR$ D WHERE U.USER#=O.OWNER# AND O.OBJ#=D.OBJ#; Все файлы с этой директории должны быть скопированы на сервер Список внешних таблиц Они также используют директории Oracle. Их содержание должно быть скопировано и исследовано. SQL> SELECT O.NAME, D.DEFAULT_DIR FROM SYS.OBJ$ O, SYS.EXTERNAL_TAB$ D WHERE D.OBJ# = O.OBJ#; Системный монитор (SMON) MON_MOD$ Table Таблица SMON MON_MOD$ table содержит информацию о The System Monitor (SMON) MON_MOD$ Table о том, какие Действия DML были выполнены в какой таблице. SQL> SELECT U.NAME AS "OWNER", O.NAME AS "OBJECT", M.OBJ#, M.INSERTS, M.UPDATES, M.DELETES, M.TIMESTAMP FROM SYS.MON_MODS$ M, SYS.USER$ U, SYS.OBJ$ O WHERE O.OBJ#=M.OBJ# AND U.USER#=O.OWNER#; Получение информации о триггерах Триггеры могут быть используемые взломщиками по механизму бекдора или как логическая бомба, поэтому нуждаются в проверке, особенно те, которые выполняются при загрузке системы, выключении, входе в систему и т.д. Запрос ниже будет содержать список активных триггеров SQL> SELECT U.NAME AS "OWNER", O.NAME AS "ENABLED_TRIGGER_NAME", DECODE(T.TYPE#, 0, 'BEFORE',2, 'AFTER','NOTSET') AS "WHEN" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER# AND ENABLED=1; Изменение “AND ENABLED=1” на “AND ENABLED=0” покажет не активные триггеры. Поиск включенных триггеров, выполняющихся после запуска системы: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "ENABLED_TRIGGER_NAME" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER# AND ENABLED=1 AND BITAND(T.SYS_EVTS,1) = 1; Поиск включенных триггеров, выполняющихся перед запуском системы: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "ENABLED_TRIGGER_NAME" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER# AND ENABLED=1 AND BITAND(T.SYS_EVTS,2) = 2; Поиск включенных триггеров, выполняющихся после входа в систему: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "ENABLED_TRIGGER_NAME" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER# AND ENABLED=1 AND BITAND(T.SYS_EVTS,8) = 8; Поиск включенных триггеров, перед выходом из системы: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "ENABLED_TRIGGER_NAME" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER# AND ENABLED=1 AND BITAND(T.SYS_EVTS,16) = 16; Получить список всех триггеров SQL> SET LONG 10000000 SQL> SELECT U.NAME AS "OWNER", O.NAME AS "TRIGGER_NAME", T.ACTION# AS "TEXT" FROM SYS.OBJ$ O, SYS.TRIGGER$ T, SYS.USER$ U WHERE O.OBJ#=T.OBJ# AND O.OWNER# = U.USER#; Получить сорс с помощью запроса в таблицу SOURCE$: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROCEDURE", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=12; Проверка контрольной суммы триггера Анонимный блок PL/SQL захеширует текст каждого триггера, поэтому данные хеши могут быть сравнены с списком известных. Так можно быстро узнать, какие были изменены: Code: DECLARE TYPE C_TYPE IS REF CURSOR; CV C_TYPE; V_ONAME VARCHAR2(30); V_OWNER VARCHAR2(30); V_OBJID NUMBER:=52296; V_HASH NUMBER:=0; V_BUFFER LONG(32767); CUR NUMBER; RES NUMBER; POS NUMBER; LEN NUMBER; BEGIN DBMS_OUTPUT.ENABLE(1000000); OPEN CV FOR 'SELECT U.NAME,O.NAME,O.OBJ# FROM SYS.OBJ$ O, SYS.USER$ U WHERE U.USER# = O.OWNER# AND O.TYPE# = 12 ORDER BY U.NAME'; LOOP FETCH CV INTO V_OWNER,V_ONAME,V_OBJID; EXIT WHEN CV%NOTFOUND; CUR:=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(CUR,'SELECT T.ACTION# FROM SYS.TRIGGER$ T WHERE T.OBJ# = :1',DBMS_SQL.NATIVE); DBMS_SQL.BIND_VARIABLE(CUR, ':1', V_OBJID); DBMS_SQL.DEFINE_COLUMN_LONG (CUR, 1); RES := DBMS_SQL.EXECUTE_AND_FETCH (CUR); IF RES > 0 THEN POS:=0; V_HASH:=0; LOOP DBMS_SQL.COLUMN_VALUE_LONG( CUR,1,32767,POS,V_BUFFER,LEN); EXIT WHEN LEN = 0; V_HASH:= V_HASH + SYS.DBMS_UTILITY.GET_HASH_VALUE (V_BUFFER,1,1073741824); POS := POS + LEN; END LOOP; DBMS_SQL.CLOSE_CURSOR (CUR); END IF; DBMS_OUTPUT.PUT_LINE(V_OWNER||'.'||V_ONAME||':'||V_HASH); V_BUFFER:=NULL; END LOOP; CLOSE CV; END; / Получится что-то вроде … … SYS.OLAPISTARTUPTRIGGER:443575894 SYS.OLAPISHUTDOWNTRIGGER:473426999 SYS.PREVENT_DDL:283296376 SYS.VANISH:797468158 SYSMAN.MGMT_METRIC_COLL_DEL:731772430 SYSMAN.MGMT_SQL_METRIC_TR:91156933 … Получение информации о просмотрах Views Views могут быть использованы атакующим для скрытия информации. Поэтому, текст всех Views должен быть получен. Особое внимание стоит уделить начинающимся на DBA, особенно DBA_VIEWS, DBA_USERS, DBA_ROLE_PRIVS, DBA_TAB_PRIVS и DBA_JOBS. SQL> SET LONG 100000000 SQL> SELECT U.NAME AS "OWNER", O.NAME AS "VIEW", V.TEXT FROM SYS.VIEW$ V, SYS.OBJ$ O, SYS.USER$ U WHERE O.OBJ#=V.OBJ# AND O.OWNER#=U.USER# ORDER BY U.NAME; Проверка контрольной суммы view text Анонимный блок PL/SQL хеширует view text поэтому, как и в предыдущем случае, хеши могут быть сравнены с списком известных. Таким образом, модифицированные будут определены Code: DECLARE TYPE C_TYPE IS REF CURSOR; CV C_TYPE; V_ONAME VARCHAR2(30); V_OWNER VARCHAR2(30); V_OBJID NUMBER:=52296; V_HASH NUMBER:=0; V_BUFFER LONG(32767); CUR NUMBER; RES NUMBER; POS NUMBER; LEN NUMBER; BEGIN DBMS_OUTPUT.ENABLE(1000000); OPEN CV FOR 'SELECT U.NAME,O.NAME,O.OBJ# FROM SYS.OBJ$ O, SYS.USER$ U WHERE U.USER# = O.OWNER# AND O.TYPE# = 4 ORDER BY U.NAME, O.NAME'; LOOP FETCH CV INTO V_OWNER,V_ONAME,V_OBJID; EXIT WHEN CV%NOTFOUND; CUR:=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(CUR,'SELECT V.TEXT FROM SYS.VIEW$ V WHERE V.OBJ# = :1',DBMS_SQL.NATIVE); DBMS_SQL.BIND_VARIABLE(CUR, ':1', V_OBJID); DBMS_SQL.DEFINE_COLUMN_LONG (CUR, 1); RES := DBMS_SQL.EXECUTE_AND_FETCH (CUR); IF RES > 0 THEN POS:=0; V_HASH:=0; LOOP DBMS_SQL.COLUMN_VALUE_LONG( CUR,1,32767,POS,V_BUFFER,LEN); EXIT WHEN LEN = 0; V_HASH:= V_HASH + SYS.DBMS_UTILITY.GET_HASH_VALUE (V_BUFFER,1,1073741824); POS := POS + LEN; END LOOP; DBMS_SQL.CLOSE_CURSOR (CUR); END IF; DBMS_OUTPUT.PUT_LINE(V_OWNER||'.'||V_ONAME||':'||V_HASH); V_BUFFER:=NULL; END LOOP; CLOSE CV; END; / Результат будет похожим на … … SYS.DBA_UNUSED_COL_TABS:215069642 SYS.DBA_UPDATABLE_COLUMNS:377298913 SYS.DBA_USERS:958803668 SYS.DBA_USTATS:203495787 SYS.DBA_VARRAYS:670521746 SYS.DBA_VIEWS:49730132 … … Получение информации обо всех библиотеках[/B] Библиотеки могут быть использованы как механизм запуска произвольного кода, поэтому нуждаются в исследовании. SQL> SELECT U.NAME AS "OWNER", O.NAME AS "LIBRARY", L.FILESPEC AS "PATH" FROM SYS.LIBRARY$ L, SYS.USER$ U, SYS.OBJ$ O WHERE O.OBJ#=L.OBJ# AND O.OWNER#=U.USER#; Все DLL, не являющиеся стандартными должны быть скопированы на сервер для исследования Получение информации о database links database links могут быть созданы взломщиком для соединения с другим сервером Oracle, Колонка CTIME обозначен когда он был создан SQL> SELECT U.NAME AS "OWNER", L.NAME AS "LINK", L.HOST, L.USERID, L.PASSWORDX, L.CTIME FROM SYS.LINK$ L, SYS.USER$ U WHERE L.OWNER#=U.USER#; Если хозяин обозначен как “PUBLIC”, link тоже является публичным и может быть использован кем угодно. . Информация о synonyms. Они могут быть использованы для влияния на выполнение PL/SQL и скрытия информации. Полный список может быть выведен таким образом: SQL> SELECT U.NAME AS "OWNER", S.OWNER AS "REAL-OWNER", S.NAME AS "OBJECT", O.NAME AS "SYNONYM" FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SYN$ S WHERE S.OBJ#=O.OBJ# AND O.OWNER#=U.USER#; Получение информации о database jobs Они могут быть использованы для изменений в настройке времени и даты – даже когда атакующий на входил в систему. Также, был опубликован rootkits от Cesar Cerrudo, работающий по данному принципу. SQL> SELECT JOB, LOWNER, POWNER, COWNER, LAST_DATE, NEXT_DATE, WHAT FROM SYS.JOB$; Oracle 10g выпустил the Job Scheduler, и база данных должна использовать ее функционал – информация о заданиях хранится в разных таблицах. Получение списка используемых заданий будет следующим: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "JOBNAME", J.PROGRAM_ACTION FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SCHEDULER$_JOB J WHERE J.OBJ#=O.OBJ# AND O.OWNER#=U.USER#; Даже если задание было удалено, информация о нем находится в логах, получить можно используя следующий запрос: SQL> SELECT LOG_ID, LOG_DATE, NAME, OWNER, STATUS FROM SYS.SCHEDULER$_EVENT_LOG ORDER BY LOG_ID; Для списка программ(исполняемых, блока PL/SQL, сохраняемые процедуры) ассоциируемых с job scheduler выполняется следующий запрос: Исполняемые: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROGRAM-EXECUTABLE", P.ACTION FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SCHEDULER$_PROGRAM P WHERE O.OBJ#=P.OBJ# AND U.USER#=O.OWNER# AND BITAND(P.FLAGS,32)=32; Stored Procedure: сохраняемые процедуры SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROGRAM-STORED-PROCEDURE", P.ACTION FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SCHEDULER$_PROGRAM P WHERE O.OBJ#=P.OBJ# AND U.USER#=O.OWNER# AND BITAND(P.FLAGS,4)=4; Блок PL/SQL SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROGRAM-PLSQL-BLOCK", P.ACTION FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SCHEDULER$_PROGRAM P WHERE O.OBJ#=P.OBJ# AND U.USER#=O.OWNER# AND BITAND(P.FLAGS,2)=2; Получения информации об объектах PL/SQL Процедуры: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROCEDURE", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=7; Функции: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PROCEDURE", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=8; Сборки: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PACKAGE", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=9; Package bodies: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "PACKAGE-BODY", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=11; Триггеры: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "TRIGGER", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=12; Типы: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "TYPE", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=13; Type bodies: SQL> SELECT U.NAME AS "OWNER", O.NAME AS "TYPE-BODY", S.SOURCE FROM SYS.USER$ U, SYS.OBJ$ O, SYS.SOURCE$ S WHERE O.OBJ#=S.OBJ# AND O.OWNER#=U.USER# AND O.TYPE#=14; Получение информации о Java objects Java код может быть загружен в класс как файл класса class file (bytecode), или как Java код, который может быть скопилирован. Код загружается в таблицу JOXFS, а bytecode – в IDL_UB1$. Получение Java кода SQL> SELECT U.NAME, O.NAME, S.JOXFTSRC FROM SYS.USER$ U, SYS.OBJ$ O, X$JOXFS S WHERE O.OBJ# = S.JOXFTOBN AND O.OWNER# = U.USER#; Контрольная сумма байткода Атакующий может получить модификацию байткода. Чтобы получить контрольную сумму и сравнить со списком известных можно использовать следующий код: Code: DECLARE TYPE C_TYPE IS REF CURSOR; CV C_TYPE; V_ONAME VARCHAR2(30); V_OWNER VARCHAR2(30); V_OBJID NUMBER:=52296; V_HASH NUMBER:=0; V_BUFFER RAW(32767); CUR NUMBER; RES NUMBER; POS NUMBER; LEN NUMBER; BEGIN DBMS_OUTPUT.ENABLE(1000000); OPEN CV FOR 'SELECT U.NAME,O.NAME,O.OBJ# FROM SYS.OBJ$ O, SYS.USER$ U WHERE U.USER# = O.OWNER# AND O.TYPE# = 29 ORDER BY U.NAME'; LOOP FETCH CV INTO V_OWNER,V_ONAME,V_OBJID; EXIT WHEN CV%NOTFOUND; CUR:=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(CUR,'SELECT S.PIECE FROM SYS.IDL_UB1$ S WHERE S.OBJ# = :1',DBMS_SQL.NATIVE); DBMS_SQL.BIND_VARIABLE(CUR, ':1', V_OBJID); DBMS_SQL.DEFINE_COLUMN_RAW (CUR, 1, V_BUFFER, 32767); RES := DBMS_SQL.EXECUTE_AND_FETCH (CUR); IF RES > 0 THEN POS:=0; V_HASH:=0; DBMS_SQL.COLUMN_VALUE_RAW(CUR,1,V_BUFFER); V_HASH:= V_HASH + SYS.DBMS_UTILITY.GET_HASH_VALUE (V_BUFFER,1,1073741824); DBMS_SQL.CLOSE_CURSOR (CUR); END IF; DBMS_OUTPUT.PUT_LINE(V_OWNER||'.'||V_ONAME||':'||V_HASH); V_BUFFER:=NULL; END LOOP; CLOSE CV; END; / Результат будет таков: … … SYS./bf8c3870_ConnectionStructHelp:52013415 SYS./f7546018_DatabaseInterface:766489862 SYS./ad32ba4d_DatabaseInterfaceHel:974677841 SYS./f0cd62e8_DatabaseInterfaceStu:202096582 SYS./d100f507_PropertySequenceHelp:222649136 SYS./809cbfa9_PropertyStruct:904769799 SYS./91352016_RemoteAuthentication:905079855 … … Также можно использовать этот запрос для того чтобы хешировать код других PL/SQL обьектов, также найденных в таблице IDL_UB1$. Когда все запросы были выполнены, spool файл может быть закрыт, также как и sqlplus. SQL> SPOOL OFF SQL> QUIT Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 – Production With the Partitioning, OLAP and Data Mining options C:\oracle\product\10.2.0\db_1\BIN> После отключения от сервера, нужно получить контрольную сумму md5 из spool file и записать её в присутствии свидетеля. Заключение После получения и сохранения всех данных Живого ответа, возможны несколько вариантов действий. Первое – отключить систему от сети и перейти к доказательства, конечно, если предполагается привлекать взломщика к юридической ответственности. Итак, аудитор системы должен найти, как взломщик пробрался в систему и дать рекомендации по безопасности. Thanks to Neminem for help=) Оригинал статьи: http://milw0rm.org/papers/158 (pdf)