24. November 2008

Mehr Sicherheit in Oracle11g: PL/SQL Netzwerk ACL

English title: Oracle11g is more secure: PL/SQL Networking ACLs

Oracle11g wird ja mehr und mehr genutzt. Und eine Erfahrung, die jeder Nutzer von UTL_SMTP, UTL_HTTP und anderen "Netzwerk"-Paketen auf Oracle11g macht ist, dass sie irgendwie nicht mehr funktionieren ... das sieht dann typischerweise so aus:
More and more people are actually working with Oracle11g and everyone who works with the PL/SQL network packages makes the same experience: Calls to UTL_SMTP, UTL_HTTP or the other network related PL/SQL packages don't work anymore - this looks then like the following ...
SQL> select httpuritype('www.oracle.de').getclob() from dual;
ERROR:
ORA-29273: HTTP-Anforderung nicht erfolgreich
ORA-06512: in "SYS.UTL_HTTP", Zeile 1674
ORA-24247: Netzwerkzugriff von Zugriffskontrollliste (ACL) abgelehnt
ORA-06512: in "SYS.HTTPURITYPE", Zeile 34
Am EXECUTE-Privileg liegt es nicht ... das ist vorhanden. Trotzdem gelingt der Netzwerkzugriff nicht. Grund ist ein in Oracle11g neu eingeführtes Sicherheitskonzept: Netzwerkzugriffe, welche durch PL/SQL-Pakete erfolgen, müssen vom DBA separat freigegeben werden.
It's not the missing EXECUTE privilege - this was granted. But the network access is blocked though. The reason is a new security concept for PL/SQL network access in Oracle11g. Such network access needs additional privileges.
Auf den ersten Blick macht das mehr Arbeit - genauer betrachtet ist das meiner Meining nach jedoch eins der besten Sicherheitsfeatures in Oracle11g. Man denke nur an einen Hacker, der durch eine SQL Injection-Lücke in die Datenbank eindringt und feststellt, dass er Zugriff auf das UTL_HTTP-Paket hat ... er kann nun neben der Datenbank auch auf das gesamte Netzwerk (welches von der Datenbank erreicht werden kann) zugreifen. Genau aus diesem Grund existiert auch die Empfehlung, das EXECUTE-Privileg auf diese Netzwerkpakete von PUBLIC zu entfernen (REVOKE EXECUTE on UTL_HTTP from PUBLIC) und es nur den Nutzern zu vergeben, die es wirklich brauchen.
At the first glance this is just more work: but IMHO this is one of the best security features in Oracle11g - ist think about a hacker which gets into your database via a SQL injection vulnerability. As soon as he finds out that he can use UTL_HTTP he gains access not only to the database but also to the network areas the database server is connected to. And exactly this is the reason for the "official" recommendation to revoke exceute privileges on those "network packages" from PUBLIC.
In Oracle11g kann, nein muss der Netzwerkzugriff für die einzelnen Ziele separat und feinganular freigegegeben werden. Und das geht mit dem neuen PL/SQL-Paket DBMS_ACL_ADMIN so:
Recap: In Oracle11g network access privileges can, no must be granted fine-grained. And this is done with the new PL/SQL package DBMS_ACL_ADMIN.
begin
  begin
    dbms_network_acl_admin.drop_acl(
      acl =>         'HTTP_OracleDe.xml'
    );
  exception 
    when others then null; -- ACL does not exist yet
  end;
  -- Privilege to connect to a host
  dbms_network_acl_admin.create_acl(
    acl =>         'HTTP_OracleDe.xml',
    description => 'HTTP-Connects zu www.oracle.de',
    principal =>   'CCZARSKI', -- DB Schema (grantee)
    is_grant =>    true,
    privilege =>   'connect',
    start_date  => null, 
    end_date  =>   null
  );
  -- Privilege to resolve a hostname (DNS lookup)
  DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
    acl =>         'HTTP_OracleDe.xml',
    principal =>   'CCZARSKI', -- DB Schema (grantee)
    is_grant  =>   true,
    privilege =>   'resolve'
    start_date  => null, 
    end_date  =>   null
  );
  -- Privilege to connect to www.oracle.de
  dbms_network_acl_admin.assign_acl(
    acl =>         'HTTP_OracleDe.xml',
    host =>        'www.oracle.de',
    lower_port =>  80,
    upper_port =>  80
  );
  -- Privilege to connect to www.oracle.com (oracle.de is redirected to oracle.com)
  dbms_network_acl_admin.assign_acl(
    acl =>         'HTTP_OracleDe.xml',
    host =>        'www.oracle.com',
    lower_port =>  80,
    upper_port =>  80
  );
end;
/
    
commit
/
Diese Aufrufe schalten die Server www.oracle.de und www.oracle.com auf Port 80 frei. Wie Ihr an den Aufrufen erkennen könnt (Parameter is_grant, start_date und end_date), können Privilegien für bestimmte Zeiträume vergeben werden und neben "positiven" ACL's können auch "negative" Privilegien vergeben werden; á la "Das ganze Subnet "192.168.10.0", aber nicht den Server "192.168.10.88". Als "grantee" können wie immer auch Rollen und auch PUBLIC eingetragen werden. Und so kann man sich auch ein Skript schreiben, welches den "alten" Oracle10g-Zustand wiederherstellt - wobei ich davon für Produktionssysteme dringend abraten möchte; die ACLs sind ein echter Sicherheitsgewinn und es wäre töricht, sie abzuschalten. Auf einer Entwicklermaschine oder für den Übergang kann das folgende Skript aber ganz hilfreich sein:
The calls grant HTTP access (port 80) to www.oracle.de and www.oracle.com to the database schema or role CCZARSKI. As you can see the parameters is_grant, start_date and end_date allow to restrict network access ("negative" privileges) or to grant a privilege only for a particular timeframe. So a grant might include the whole subnet 192.168.10.0 but not the host 192.168.10.88. Not only database schemas can be used as grantees but also roles and PUBLIC. Having this in mind it's easy to write a script which restores 10g behaviour in 11g: I'd strongly recommand not to run this in a production environment - it makes the system less secure! But for a development server or for a migration period this might be helpful.
begin
  begin
    dbms_network_acl_admin.drop_acl(
      acl =>         'all-network-PUBLIC.xml'
    );
  exception 
    when others then null;  
  end;
  dbms_network_acl_admin.create_acl(
    acl =>         'all-network-PUBLIC.xml',
    description => 'Netzwerk-Connects fuer ALLE',
    principal =>   'PUBLIC',
    is_grant =>    true,
    privilege =>   'connect'
  );
  DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
    acl =>         'all-network-PUBLIC.xml',
    principal =>   'PUBLIC', 
    is_grant  =>   true,
    privilege =>   'resolve'
  );
  dbms_network_acl_admin.assign_acl(
    acl =>         'all-network-PUBLIC.xml',
    host =>        '*'
  );
end;
/
sho err
    
commit
/
Eine Dictionary View für die ACLs gibt es auch: DBA_NETWORK_ACLS. Ach ja: noch etwas Wichtiges: Wie man an den "Dateinamen" für die ACL erkennen kann, ist hier XML im Spiel. Und tatsächlich: Die ACLs werden als XML in der XMLDB (dem XML DB Repository) gespeichert. Ab Oracle11g gilt also: Wenn man mit den genannten PL/SQL Netzwerk-Paketen arbeiten möchte, muss die XML DB in der Datenbank vorhanden sein.
There is also a dictionary view for the ACLs: DBA_NETWORK_ACLS. And by the way: The ACLs are actually stored in the XML DB Repository - XML DB functionality is being used for the ACL implementation. That means that if you want to use PL/SQL network packages in Oracle11g you must have XML DB enabled in your database.
Mehr Informationen zum Thema findet Ihr in der Oracle-Dokumentation.
More information is contained in the Oracle documentation.

1 Kommentar:

Sokrates hat gesagt…

Hallo Herr Czarski

prima, danke fuer den Artikel, helpful !

Sokrates

Beliebte Postings