 |
|
Packages without Ready Made Checksums - 9i and 8i
Oracle Forensics tips by Paul Wright
|
Using the dbms_utility.get_hash_value utility
it is possible to gain the checksum of a vulnerable package and then
compare it to a known bad checksum in the check as below. (see Oracle
Hacker's Handbook):
I have extended this query into a one off
checksum checker as below.
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
SDO_CATALOG_IS_VULNERABLE
FROM
DBA_SOURCE WHERE OWNER='MDSYS' AND NAME='SDO_CATALOG') INTERSECT
(select 1605825224.777777777777777777777777777778 FROM DUAL);
Note that DBMS_OBFUSCATIONTOOLKIT and
DBMS_CRYPTO are not applicable across 8, 9 and 10g hence the use of
DBMS_UTILITY.
If any of these queries below return positive
then they have a vulnerable status as per the January 2007 CPU.
plsqlchecksums.sql January 2007 CPU
--
MDSYS.SDO_CATALOG
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
SDO_CATALOG_IS_VULNERABLE
FROM
DBA_SOURCE WHERE OWNER='MDSYS' AND NAME='SDO_CATALOG')INTERSECT
(select
1605825224.777777777777777777777777777778 FROM DUAL);
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
DBMS_AQ_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND NAME='DBMS_AQ')INTERSECT
(select
1798692409.000000000000000000000000000000 FROM DUAL);
--SYS.DBMS_DRS
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
DBMS_DRS_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND NAME='DBMS_DRS')
INTERSECT
(select 1492058698.038147138964577656675749318801 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
MD_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND NAME='MD')INTERSECT
(select
1643590615.642857142857142857142857142857 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
REPCAT_UNTRUSTED_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1202579658.000000000000000000000000000000 FROM DUAL);
--SYS.DBMS_LOGREP_UTIL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
LOGREP_UTIL_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_LOGREP_UTIL')INTERSECT
(select
1751593761.250000000000000000000000000000 FROM DUAL);
--SYS.DBMS_CAPTURE_ADM_INTERNAL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30))) as
CAPTURE_ADM_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND NAME='DBMS_CAPTURE_ADM_INTERNAL')INTERSECT
(select
1434196575.666666666666666666666666666667 FROM DUAL);
-- Windows
9i January 2007 CPU vulnerable.
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_AQ_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_AQ')INTERSECT
(select
1443715512.263157894736842105263157894737 FROM DUAL);
--SYS.DBMS_DRS
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_DRS_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_DRS')INTERSECT
(select
1514810796.460750853242320819112627986348 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
MD_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND
NAME='MD')INTERSECT
(select
1561926250.552511415525114155251141552511 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_IS_VULNERABLE FROM DBA_SOURCE WHERE
OWNER='SYS' AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1354665900.600000000000000000000000000000 FROM DUAL);
--w8i
January 2007 CPU vulnerable.
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_AQ_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_AQ')INTERSECT
(select
1544412343.330695308083663086489542114189 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
MD_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND
NAME='MD')INTERSECT
(select
1530597204.207900547967612660505438783021 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1580496068.385563380281690140845070422535 FROM DUAL);
-- UNIX 10g
January 2007 CPU vulnerable.
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_AQ_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_AQ')INTERSECT
(select
1798692409.000000000000000000000000000000 FROM DUAL);
--SYS.DBMS_DRS
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_DRS_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_DRS')INTERSECT
(select
1492058698.038147138964577656675749318801 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
MD_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND
NAME='MD')INTERSECT
(select
1643590615.642857142857142857142857142857 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1202579658.000000000000000000000000000000 FROM DUAL);
--SYS.DBMS_LOGREP_UTIL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
LOGREP_UTIL_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_LOGREP_UTIL')INTERSECT
(select
1751593761.250000000000000000000000000000 FROM DUAL);
--SYS.DBMS_CAPTURE_ADM_INTERNAL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
ADM_INTERNAL_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_CAPTURE_ADM_INTERNAL')INTERSECT
(select
1434196575.666666666666666666666666666667 FROM DUAL);
-- UNIX 9i
January 2007 CPU vulnerable.
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_AQ_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_AQ')INTERSECT
(select
1547384936.437500000000000000000000000000 FROM DUAL);
--SYS.DBMS_DRS
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_DRS_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_DRS')INTERSECT
(select
1486938122.644021739130434782608695652174 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
MD_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND
NAME='MD')INTERSECT
(select
1591974403.452229299363057324840764331210 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1447600354.333333333333333333333333333333 FROM DUAL);
--SYS.DBMS_LOGREP_UTIL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
LOGREP_UTIL_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_LOGREP_UTIL')INTERSECT
(select
1560944522.944444444444444444444444444444 FROM DUAL);
--SYS.DBMS_CAPTURE_ADM_INTERNAL
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
ADM_INTERNAL_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_CAPTURE_ADM_INTERNAL')INTERSECT
(select
1614291519.272727272727272727272727272727 FROM DUAL);
-- UNIX 8i
January 2007 CPU vulnerable.
--SYS.DBMS_AQ
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
DBMS_AQ_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS' AND
NAME='DBMS_AQ')INTERSECT
(select
1541762263.406942701798410706817231283982 FROM DUAL);
--MDSYS.MD
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
MD_IS_VULNERABLE FROM DBA_SOURCE WHERE OWNER='MDSYS' AND
NAME='MD')INTERSECT
(select
1530584731.799748704256321658551908277054 FROM DUAL);
--SYS.DBMS_REPCAT_UNTRUSTED
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1576988215.418508287292817679558011049724 FROM DUAL)
Of interest is the fact that even though the
January CPU is fully installed correctly on 10.2.0.1 unbreakable
Linux box as shown below.
SQL> select * from v$version;
BANNER
---------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0
Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
SQL>
SELECT COMMENTS FROM DBA_REGISTRY_HISTORY;
COMMENTS
--------------------------------------------------------------------------------
CPUJan2007
SQL>
(SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
2 (select 1202579658.000000000000000000000000000000 FROM
DUAL);
REPCAT_UNTRUSTED_VULNERABLE
---------------------------
1202579658
This is the same code as this unpatched 10.1
machine:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - 64bi
PL/SQL Release 10.1.0.2.0 - Production
CORE 10.1.0.2.0
Production
TNS for Solaris: Version 10.1.0.2.0 - Production
NLSRTL Version 10.1.0.2.0 - Production
SQL> --SYS.DBMS_REPCAT_UNTRUSTED
SQL> (SELECT
AVG(dbms_utility.get_hash_value(text,1000000000,power(2,30)))as
REPCAT_UNTRUSTED_VULNERABLE FROM DBA_SOURCE WHERE OWNER='SYS'
AND NAME='DBMS_REPCAT_UNTRUSTED')INTERSECT
(select
1202579658.000000000000000000000000000000 FROM DUAL); 2
REPCAT_UNTRUSTED_VULNERABLE
---------------------------
1202579658
What this means is the Jan 2007 CPU did not
work properly on Unbreakable Linux 10.2.0.1.0. Interestingly on
10.2.0.3.0 DBMS_REPCAT_UNTRUSTED is not vulnerable so it is the
patch that has failed to apply the non-vulnerable package despite
the CPU stating that it had been fixed. This is quite a common
experience.This fact proves the value of checking the
vulnerabilities individually which can only be done when the
vulnerabilities are understood.
There will of course be cases where the package
returns a resultset from neither a vulnerable or non-vulnerable
signature and in that case it would be an unknown.
There is a reasonable possibility that the
size, checksum, name of the package could have changed due to a
procedure within the package being changed or deleted but still
leaving a vulnerable procedure within the package as a whole. This
would leave the package with an unknown checksum.
It is possible to automate the collection of
all checksums in privileged schemas from database in order to check
which packages have changed or stayed the same. Doing this will be
useful to verify the patch has worked and also to see what
vulnerabilities have been fixed that may not have been publicly
disclosed. Lastly the automated method I will show in the next
section will also be relevant to identifying database malware which
will be the subject of a following chapter.
In order to avoid malware such as rootkits
which change the way in which VIEWS report it is useful to translate
the previous style of check into a query that uses the base tables
and additionally uses the timestamp of the package as added
verification.
This is an excerpt from the book "Oracle
Forensics: Oracle Security Best Practices", by Paul M. Wright,
the father of Oracle Forensics.