Wed 1 Sep 2010
So, we all know that Oracle used to be non-case sensitive when it came to user names and passwords. We also know that since 11g this is not the case and Oracle, by default, is case sensitive.
The one thing I wanted to point out is that even if you are using sec_case_sensitive_logon=false and ignore the case of passwords for backward compatibility, Oracle will still compute the spare4 field (hash) just in case you will turn the parameter to true.
This means that when you choose passwords, you should actually choose a mixed-case password even if it does not matter right now because if an attacker will get access to your hashes, mixing the case will make them harder to break. One has to remember that calculating the hash is much faster than the older algorithm (the password field) so an attacker will probably try the spare4 field first.
How many of you are actually using a mixed case password for Oracle accounts?
Thu 19 Aug 2010
Sometimes, you want to enhance or change system stored procedures to add functionality like security related code. This is not supported and might blow up in your face so all the standard caveats apply. If it blows in your face, tough luck!
SQL2000 is pretty straight forward and you can find plenty of places on the web that will help you with the details.
Using SQL2005 and SQL2008 the process is a bit more complicated:
1. Stop SQL Server service.
2. On command prompt run the following command to run the server in single user mode – be sure to replace the MSSQLSERVER with the actual instance name
C:\>”C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe” -sMSSQLSERVER -m
3. Connect to SQL server with SSMS as ADMIN:HOSTNAME
4. Run the following to change the database to the system resource database: “USE mssqlsystemresource”
5. Run the following to change the database to read-write – “alter database mssqlsystemresource set read_write”
6. Run the following to load the text of the procedure – exec sp_helptext ‘stored procedure name you want to change’
7. Alter the procedure and add the relevant code – “alter procedure …”
8. Return the system resource database to read-only – “alter database mssqlsystemresource set read_only”
9. Shutdown the instance – “shutdown”
10. Start the instance using the service as usual
And, that is it. A somewhat complex process to change a system stored procedure.
Thu 15 Jul 2010
Posted by Slavik under security
No Comments
Next week I’ll be doing a really fun webcast, as a guest speaker for McAfee’s ‘Hacking Exposed Live’ series. The series takes a look at current and evolving hacks and what you can do to protect your environment. The topic is officially: ‘Understanding Threat Vectors for Database Breaches’, and I’ll be showing some sample attacks based on ways a rogue insider might try to breach various levels of data security, assuming they had physical access to the network and/or servers.
Please join us if you can:
Thu, Jul 22, 2010 @ 11:00am PDT (click here to register)
Thu 8 Apr 2010
Alex wrote a nice blog post showing that the 0day found by David Litchfield [pdf] is now fixed in the newest Oracle 11.2.0.1 release for Windows. He has some analysis of the fix as well as some good examples of using Repscan to view permissions and audit records using the online browser.
Whenever I need to check some security related (and sometimes non-security related) stuff in the database, I find myself using Repscan online browser more and more because of its ease of use and prepared queries.
Good stuff, Alex.
Tue 6 Apr 2010
During the weekend, I stumbled across an interesting project named pysql. The project aims to replace SQL*Plus with a sane shell written in Python with history, tab completion and many extensions. Being a veteran of using SQL*Plus, I know that some of the above can be actually achieved on Linux/Unix environments with SQL*Plus using a handy utility called rlwrap but I was still curios.
The installation is a breeze (as long as you already have Python and cx_Oracle installed correctly). Just unzip into a directory and run pysql.sh. First impression – this is really cool stuff. Out of the box you get coloring, correct terminal handling, help, implemented macros and even visual graphs. The only problem I had was the lack of any documentation (that I could find) about how to use it all. Source code browsing is good and all but I would have preferred an easy how-to document.
Oh, and I stumbled across a bug (that Sébastien Renard told me is already fixed in the next version) that would not allow me to connect “/ as sysdba”. I did a small fix in pysqlshell.py that allowed me to easily fix the issue (just replace these 2 functions):
def __connect(self, connectString, mode=""):
"""Calls the PysqlDb class to connect to Oracle"""
sid = None
count=connectString.count("@")
if count==1:
(connectString, sid)=connectString.split("@")
elif count > 1:
raise PysqlException(_("Invalid connection string"))
count=connectString.count("/")
if count==0:
user=connectString
try:
passwd=getpass()
except (Exception):
raise PysqlException(_("Invalid connection string"))
elif count == 1:
(user, passwd)=connectString.split("/")
else:
raise PysqlException(_("Invalid connection string"))
if sid==None:
connectString = user + "/" + passwd
else:
connectString = user + "/" + passwd + "@" + sid
self.db=PysqlDb(connectString, mode)
self.__setPrompt()
def __setPrompt(self, blank=False, multiline=False, finishedQuery=False):
"""Sets the prompt according to the connexion state
@param blank: if true, no prompt is issue (default is False)
@param finishedQuery: if true mark prompt with a * to notify a query is finished
@type blank: bool
@type finishedQuery: bool"""
#TODO: do not update title for every line
codec=self.conf.getCodec()
if blank or not self.showPrompt:
prompt=""
elif multiline:
prompt="> "
else:
if self.db is None:
prompt=self.notConnectedPrompt
# Update the title (without color else it is a huge mess)
setTitle(_("Pysql - Not connected"), codec)
else:
sid = self.db.getDSN() if self.db.getDSN() != "None" else os.environ["ORACLE_SID"]
userName = self.db.getUsername() if self.db.getUsername() != "" else "/"
prompt=userName+"@"+sid+" "
if finishedQuery:
prompt+="* "
setTitle("Pysql - %s" % prompt, codec)
self.prompt=prompt.encode(codec, "replace")
This project is definitely on my “keep-an-eye-on” list.
Is anybody else using this?
Wed 31 Mar 2010
Paul Wright published an interesting post about how you can find traces of Java privilege escalation attacks in the database. Great stuff!
Of course, Hedgehog already protects against these published attacks as Paul showed earlier here. Hedgehog comes with build-in vPatch protections that cover the DBMS_JVM_EXP_PERMS and DBMS_JAVA attacks.
Tue 30 Mar 2010
Tanel published a great post a while ago talking about Oracle’s sql_id and hash values in Oracle 10g+. I wanted to be able to compute sql_id and hash values directly from SQL statements for our Hedgehog product. I did a few tests and could not match the MD5 value generated from the SQL statement to the MD5 value Oracle is calculating in X$KGLOB.KGLNAHSV. After a short discussion with Tanel, it turned out that Oracle is appending a NULL (‘\0′) value to the statement and then calculates the MD5.
Here is a test and some code in Python:
SYS> select 'Slavik' from dual;
'SLAVI
------
Slavik
SYS> select kglnahsv, kglnahsh from x$kglob where kglnaobj =
'select ''Slavik'' from dual';
KGLNAHSV KGLNAHSH
--------------------------------- ----------
7a483e90555ab4ad24e190abe3e7775d 3823597405
7a483e90555ab4ad24e190abe3e7775d 3823597405
SYS> select sql_id, hash_value, old_hash_value from v$sql where sql_text =
'select ''Slavik'' from dual';
SQL_ID HASH_VALUE OLD_HASH_VALUE
------------- ---------- --------------
29schpgjyfxux 3823597405 3501236764
So, first, let's check that our MD5 matches:
>>> import hashlib
>>> import math
>>> import struct
>>> stmt = "select 'Slavik' from dual"
>>> d = hashlib.md5(stmt + '\x00').digest()
>>> struct.unpack('IIII', d)[3]
3823597405
>>> h = ''
>>> for i in struct.unpack('IIII', d):
h += hex(i)[2:]
>>> h
'7a483e90555ab4ad24e190abe3e7775d'
Good, all seem to match!
Now, let's create some utility functions:
def sqlid_2_hash(sqlid):
sum = 0
i = 1
alphabet = '0123456789abcdfghjkmnpqrstuvwxyz'
for ch in sqlid:
sum += alphabet.index(ch) * (32**(len(sqlid) - i))
i += 1
return sum % (2 ** 32)
def stmt_2_sqlid(stmt):
h = hashlib.md5(stmt + '\x00').digest()
(d1,d2,msb,lsb) = struct.unpack('IIII', h)
sqln = msb * (2 ** 32) + lsb
stop = math.log(sqln, math.e) / math.log(32, math.e) + 1
sqlid = ''
alphabet = '0123456789abcdfghjkmnpqrstuvwxyz'
for i in range(0, stop):
sqlid = alphabet[(sqln / (32 ** i)) % 32] + sqlid
return sqlid
def stmt_2_hash(stmt):
return struct.unpack('IIII', hashlib.md5(stmt + '\x00').digest())[3]
Let's try them...
>>> stmt_2_hash(stmt)
3823597405
>>> stmt_2_sqlid(stmt)
'29schpgjyfxux'
>>> sqlid_2_hash(stmt_2_sqlid(stmt))
3823597405
Well, it all works. Now, to the real programming…
Sun 7 Mar 2010
Posted by Slavik under Oracle, security
[4] Comments
As you can see here, the Python code handles a specific case of Oracle TNS layer requesting a RESEND of the last packet. I’ve noticed that no matter what client I’m trying to connect with, Oracle is always requesting a RESEND after the initial CONNECT request as you can see here (removed various ACK packets, etc.):
1. Using SQL*Plus
Packet number 13:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 63055
Dst port: 1521
Packet Type: Connect
Version: 01 3a
SDU/TDU: 8192 / 32512
SERVICE_NAME: db11200
SID: <N/A>
HOST: slavik-laptop
PROGRAM: sqlplus
USER: slavik
Payload (216 bytes):
00000 00 d8 00 00 01 00 00 00 01 3a 01 2c 0c 41 20 00 .........:.,.A .
00016 7f ff 7f 08 00 00 01 00 00 9e 00 3a 00 00 08 00 ...........:....
00032 41 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AA..............
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 45 52 56 49 43 45 5f 4e 41 DATA=(SERVICE_NA
00096 4d 45 3d 64 62 31 31 32 30 30 29 28 43 49 44 3d ME=db11200)(CID=
00112 28 50 52 4f 47 52 41 4d 3d 73 71 6c 70 6c 75 73 (PROGRAM=sqlplus
00128 29 28 48 4f 53 54 3d 73 6c 61 76 69 6b 2d 6c 61 )(HOST=slavik-la
00144 70 74 6f 70 29 28 55 53 45 52 3d 73 6c 61 76 69 ptop)(USER=slavi
00160 6b 29 29 29 28 41 44 44 52 45 53 53 3d 28 50 52 k)))(ADDRESS=(PR
00176 4f 54 4f 43 4f 4c 3d 54 43 50 29 28 48 4f 53 54 OTOCOL=TCP)(HOST
00192 3d 31 32 37 2e 30 2e 30 2e 31 29 28 50 4f 52 54 =127.0.0.1)(PORT
00208 3d 31 35 32 31 29 29 29 =1521)))
Packet number 15:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 63055
Packet Type: Resend
Payload (8 bytes):
00000 00 08 00 00 0b 00 00 00 ........
Packet number 17:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 63055
Dst port: 1521
Packet Type: Connect
Version: 01 3a
SDU/TDU: 8192 / 32512
SERVICE_NAME: db11200
SID: <N/A>
HOST: slavik-laptop
PROGRAM: sqlplus
USER: slavik
Payload (216 bytes):
00000 00 d8 00 00 01 00 00 00 01 3a 01 2c 0c 41 20 00 .........:.,.A .
00016 7f ff 7f 08 00 00 01 00 00 9e 00 3a 00 00 08 00 ...........:....
00032 41 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AA..............
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 45 52 56 49 43 45 5f 4e 41 DATA=(SERVICE_NA
00096 4d 45 3d 64 62 31 31 32 30 30 29 28 43 49 44 3d ME=db11200)(CID=
00112 28 50 52 4f 47 52 41 4d 3d 73 71 6c 70 6c 75 73 (PROGRAM=sqlplus
00128 29 28 48 4f 53 54 3d 73 6c 61 76 69 6b 2d 6c 61 )(HOST=slavik-la
00144 70 74 6f 70 29 28 55 53 45 52 3d 73 6c 61 76 69 ptop)(USER=slavi
00160 6b 29 29 29 28 41 44 44 52 45 53 53 3d 28 50 52 k)))(ADDRESS=(PR
00176 4f 54 4f 43 4f 4c 3d 54 43 50 29 28 48 4f 53 54 OTOCOL=TCP)(HOST
00192 3d 31 32 37 2e 30 2e 30 2e 31 29 28 50 4f 52 54 =127.0.0.1)(PORT
00208 3d 31 35 32 31 29 29 29 =1521)))
Packet number 19:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 63055
Packet Type: Accept
Accepted: Yes
Payload (32 bytes):
00000 00 20 00 00 02 00 00 00 01 3a 0c 41 20 00 7f ff . .......:.A ...
00016 01 00 00 00 00 20 41 41 00 00 00 00 00 00 00 00 ..... AA........
2. Using JDBC Type 4
Packet number 4:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 49699
Dst port: 1521
Packet Type: Connect
Version: 01 36
SDU/TDU: 8192 / 32512
SERVICE_NAME: <N/A>
SID: db11200
HOST: __jdbc__
PROGRAM: JDBC Thin Client
USER: slavik
Payload (211 bytes):
00000 00 d3 00 00 01 00 00 00 01 36 01 2c 0e 41 20 00 .........6.,.A .
00016 7f ff 4f 98 00 00 00 01 00 99 00 3a 00 00 00 00 ..O........:....
00032 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 49 44 3d 64 62 31 31 32 30 DATA=(SID=db1120
00096 30 29 28 43 49 44 3d 28 50 52 4f 47 52 41 4d 3d 0)(CID=(PROGRAM=
00112 4a 44 42 43 20 54 68 69 6e 20 43 6c 69 65 6e 74 JDBC Thin Client
00128 29 28 48 4f 53 54 3d 5f 5f 6a 64 62 63 5f 5f 29 )(HOST=__jdbc__)
00144 28 55 53 45 52 3d 73 6c 61 76 69 6b 29 29 29 28 (USER=slavik)))(
00160 41 44 44 52 45 53 53 3d 28 50 52 4f 54 4f 43 4f ADDRESS=(PROTOCO
00176 4c 3d 74 63 70 29 28 48 4f 53 54 3d 6c 6f 63 61 L=tcp)(HOST=loca
00192 6c 68 6f 73 74 29 28 50 4f 52 54 3d 31 35 32 31 lhost)(PORT=1521
00208 29 29 29 )))
Packet number 6:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 49699
Packet Type: Resend
Payload (8 bytes):
00000 00 08 00 00 0b 00 00 00 ........
Packet number 8:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 49699
Dst port: 1521
Packet Type: Connect
Version: 01 36
SDU/TDU: 8192 / 32512
SERVICE_NAME: <N/A>
SID: db11200
HOST: __jdbc__
PROGRAM: JDBC Thin Client
USER: slavik
Payload (211 bytes):
00000 00 d3 00 00 01 00 00 00 01 36 01 2c 0e 41 20 00 .........6.,.A .
00016 7f ff 4f 98 00 00 00 01 00 99 00 3a 00 00 00 00 ..O........:....
00032 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 49 44 3d 64 62 31 31 32 30 DATA=(SID=db1120
00096 30 29 28 43 49 44 3d 28 50 52 4f 47 52 41 4d 3d 0)(CID=(PROGRAM=
00112 4a 44 42 43 20 54 68 69 6e 20 43 6c 69 65 6e 74 JDBC Thin Client
00128 29 28 48 4f 53 54 3d 5f 5f 6a 64 62 63 5f 5f 29 )(HOST=__jdbc__)
00144 28 55 53 45 52 3d 73 6c 61 76 69 6b 29 29 29 28 (USER=slavik)))(
00160 41 44 44 52 45 53 53 3d 28 50 52 4f 54 4f 43 4f ADDRESS=(PROTOCO
00176 4c 3d 74 63 70 29 28 48 4f 53 54 3d 6c 6f 63 61 L=tcp)(HOST=loca
00192 6c 68 6f 73 74 29 28 50 4f 52 54 3d 31 35 32 31 lhost)(PORT=1521
00208 29 29 29 )))
Packet number 10:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 49699
Packet Type: Accept
Accepted: Yes
Payload (32 bytes):
00000 00 20 00 00 02 00 00 00 01 36 0e 41 20 00 7f ff . .......6.A ...
00016 01 00 00 00 00 20 41 01 00 00 00 00 00 00 00 00 ..... A.........
3. Using an OCI with 10g client
Packet number 4:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 40196
Dst port: 1521
Packet Type: Connect
Version: 01 39
SDU/TDU: 2048 / 32512
SERVICE_NAME: db11200
SID: <N/A>
HOST: slavik-laptop
PROGRAM: ocitest
USER: slavik
Payload (216 bytes):
00000 00 d8 00 00 01 00 00 00 01 39 01 2c 0c 01 08 00 .........9.,....
00016 7f ff 7f 08 00 00 01 00 00 9e 00 3a 00 00 02 00 ...........:....
00032 41 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AA..............
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 45 52 56 49 43 45 5f 4e 41 DATA=(SERVICE_NA
00096 4d 45 3d 64 62 31 31 32 30 30 29 28 43 49 44 3d ME=db11200)(CID=
00112 28 50 52 4f 47 52 41 4d 3d 6f 63 69 74 65 73 74 (PROGRAM=ocitest
00128 29 28 48 4f 53 54 3d 73 6c 61 76 69 6b 2d 6c 61 )(HOST=slavik-la
00144 70 74 6f 70 29 28 55 53 45 52 3d 73 6c 61 76 69 ptop)(USER=slavi
00160 6b 29 29 29 28 41 44 44 52 45 53 53 3d 28 50 52 k)))(ADDRESS=(PR
00176 4f 54 4f 43 4f 4c 3d 54 43 50 29 28 48 4f 53 54 OTOCOL=TCP)(HOST
00192 3d 31 32 37 2e 30 2e 30 2e 31 29 28 50 4f 52 54 =127.0.0.1)(PORT
00208 3d 31 35 32 31 29 29 29 =1521)))
Packet number 6:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 40196
Packet Type: Resend
Payload (8 bytes):
00000 00 08 00 00 0b 00 00 00 ........
Packet number 8:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 40196
Dst port: 1521
Packet Type: Connect
Version: 01 39
SDU/TDU: 2048 / 32512
SERVICE_NAME: db11200
SID: <N/A>
HOST: slavik-laptop
PROGRAM: ocitest
USER: slavik
Payload (216 bytes):
00000 00 d8 00 00 01 00 00 00 01 39 01 2c 0c 01 08 00 .........9.,....
00016 7f ff 7f 08 00 00 01 00 00 9e 00 3a 00 00 02 00 ...........:....
00032 41 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AA..............
00048 00 00 00 00 00 00 00 00 00 00 28 44 45 53 43 52 ..........(DESCR
00064 49 50 54 49 4f 4e 3d 28 43 4f 4e 4e 45 43 54 5f IPTION=(CONNECT_
00080 44 41 54 41 3d 28 53 45 52 56 49 43 45 5f 4e 41 DATA=(SERVICE_NA
00096 4d 45 3d 64 62 31 31 32 30 30 29 28 43 49 44 3d ME=db11200)(CID=
00112 28 50 52 4f 47 52 41 4d 3d 6f 63 69 74 65 73 74 (PROGRAM=ocitest
00128 29 28 48 4f 53 54 3d 73 6c 61 76 69 6b 2d 6c 61 )(HOST=slavik-la
00144 70 74 6f 70 29 28 55 53 45 52 3d 73 6c 61 76 69 ptop)(USER=slavi
00160 6b 29 29 29 28 41 44 44 52 45 53 53 3d 28 50 52 k)))(ADDRESS=(PR
00176 4f 54 4f 43 4f 4c 3d 54 43 50 29 28 48 4f 53 54 OTOCOL=TCP)(HOST
00192 3d 31 32 37 2e 30 2e 30 2e 31 29 28 50 4f 52 54 =127.0.0.1)(PORT
00208 3d 31 35 32 31 29 29 29 =1521)))
Packet number 10:
From: 127.0.0.1
To: 127.0.0.1
Protocol: TCP
Src port: 1521
Dst port: 40196
Packet Type: Accept
Accepted: Yes
Payload (32 bytes):
00000 00 20 00 00 02 00 00 00 01 39 0c 01 08 00 7f ff . .......9......
00016 01 00 00 00 00 20 41 41 00 00 00 00 00 00 00 00 ..... AA........
This is using an Oracle server 11gR2 (11.2.0.1) 64bit.
So, my question is – why? Is this a clumsy attempt to thwart discovery tools? Some sort of a defense mechanism?
I would appreciate any insights here. I’m sure that there are knowledgeable people out there who know the answer.
Fri 5 Mar 2010
Posted by Slavik under sentrigo
No Comments
We had a great time at the SC magazine awards dinner on Tuesday. We were finalists in the “best SME security solution” category but unfortunately we did not win.
Here is Andy, our VP marketing before the dinner and announcements:

And here he is after some wine and us not winning:

Tue 2 Mar 2010
Posted by Slavik under RSA
1 Comment
So, I arrived to Moscone Center a bit late for the first cloud security alliance session. It turns out that there was a huge line to enter and a lot of people were left outside.
Having a free 1.5 hours, I wanted to connect and check emails. I’ve already received my password so I thought it will be a simple matter but alas, I was wrong. It turns out that the conference has instructions to connect using Windows and MacOS but no Linux instructions in sight. Thinking that it is still a simple matter, I tried several combinations of username / password but eventually gave up and approached the connect assistants. It turns out that I was missing a certificate file to authenticate the access point. With the certificate I got, I tried again but without success. I verified that everything is correctly configured and then decided to do the best thing in such situations:
Restart the machine!
As expected, everything connected and started working…
I wonder if this technique also works for cars – if your car stops, turn off the engine, exit the car and lock the doors and then unlock and start the engine. I think I will try it next time I have car problems