Call: +44 (0)7759 277220 Call
Blog

Pete Finnigan's Oracle Security Weblog

This is the weblog for Pete Finnigan. Pete works in the area of Oracle security and he specialises in auditing Oracle databases for security issues. This weblog is aimed squarely at those interested in the security of their Oracle databases.

Would you Pay to Speak at a Conference?

I was approached by a lady on LinkedIn a few weeks ago to ask me if I would speak at a conference in another country. I said that I was interested and asked for more details and importantly do they cover the travel, hotel etc. They came back to me after a couple of weeks and said that they would offer me a discounted entry to the conference and they would not cover any expenses for travel, hotel, etc.

Of course I politely declined to attend at this point. They said they are a commercial company and have to watch the bottom line BUT I am also a commercial company. Why would I pay for flights, hotel, transfers, food AND pay to enter their conference so that I could speak?Is this normal? Its the first time this has happened to me. Normally I will speak for free at conferences in the UK and drive there; its worth it in the UK, my potential business audience is here. I have spoken many times in other countries; most European countries and as far as Singapore and Dubai but always the organiser would cover the travel and accommodation and not ask me to pay an attendance fee. Some paid me a fee to speak.

If I was organising a conference then I would want the best speakers and pay their costs as it would make my event better and attract more people to attend.

#oracleace #sym_42 #oracle #database #security #speaking #conference

Passwords in Scripts and Environment Variables

There was a post a few days ago on LinkedIn by Johannes Michler about easily passing passwords to adop via a shell script when patching E-Business Suite. This script sets the password for the E-Business Suite APPS user, SYSTEM and a weblogic password by creating three environment variables that are then used to log in using the passwords in these variables.

It is a short article and part 1 of a longer series but it prompted me to write some comments on it that you can see in LinkedIn. Having written those comments I think its worth while discussing the solution to the problem that Johannes was trying to solve as its a more generic problem than just his specific case.

Over 20 years of performing security audits of Oracle databases and often where the database supports Oracle E-Business Suite I see the remnants of the solutions. I always in every audit find passwords for databases and sometimes other systems and applications on the server hosting the database. Always!

I find passwords in SQL scripts, shell scripts, text files, . (dot) scripts and files, environment variables, output files, scripts to change passwords, passwords stored in database tables, sometimes encrypted with real encryption, sometimes with pseudo encryption and sometimes in clear text and many more places.

I have always found passwords for the database that are current and often passwords for other databases. I see often that if I am reviewing the main production database and its server that DBAs use the server as a sort of personal PC and we find scripts and evidence of connections to other main databases and their servers on the server I am reviewing.

I once found all the EBS database passwords in one script on a server. The interesting thing was that these passwords were strong (15 characters, good character set...) but they were all in a script in the root directory of the Unix server.

My case is more generic as there is a clear evidence that in Johannes example and case its more defined and maybe OK. In general you should never put passwords in scripts or environment variables; These scripts will hang around and can be found by anyone like me and could be used to access the systems if the person doing the finding does not have rights to access these systems.

In Johannes case its for a patch and the server is not in use during the patch so if adding passwords to a script is faster and easier than typing them in many many times during an installation then OK; BUT. the script must be removed afterwards and not backed up. Ideally all of the passwords must be changed after the install/upgrade so that if the script is left then the passwords do not work still.

Johannes also suggested the use of OCI vault to store the passwords. This is also OK BUT if you don't use OCI then its more complex to use it just for this. If you do use OCI already then its easier as you have the OCI already and its set up already.

You can also use Oracle wallets and secure password store for local database passwords. You could also use directory based accounts or even SSL authentication in the database so there is no password but not for other systems that do not support these.

Finding a password is easier than cracking a password. Clean up, never leave scripts lying around, make sure anything with a password in a script temporarily has its password changed straight afterwards. Using scripts and passwords where the system is temporarily restricted is fine BUT only if you clean up

#oracleace #sym_42 #oracle #database #oci #vault #passwords #securepasswords #wallet #cracking #scripts

Searching Base64 Encoded text for a clear text string

I had an issue to solve where I needed to find if some base64 encoded text included a clear text string which was of course encoded in the source data. I needed to search hundreds of XML files where some nodes were Base64 encoded but the rest of the file is clear text and XML nodes. Each of the hundreds of files can also contain 1 Base64 encoded section or hundreds.

I could try and decode all the base64 encoded nodes and then search for the clear text string I needed to find but this would be time consuming as there was no simple way to just Base64 decode the relevant parts of each file without writing a custom program to parse each file, find the Base64 bits, decode them and then check each string for the clear text.

The only realistic way is to search the Bas64 encoded strings for a Base64 version of the clear text string. This is not as simple as it first sounds but is still reasonably simple. We need to know a little about how Base64 works.

The3 Base64 algorithm at a simple level takes blocks of 3 bytes (8 bits) and then splits the 3*8=24 bits into 4*6=24 bits. The 4 pieces of 6 bits are then encoded to a look up. This allows non-ascii data to be represented as ascii by using 6 bits for each piece and then looking up a printable character from the map. OK, there is more than this to Base64 but that is the high level of it for this discussion.

This means that the position of the encoded search string in the target Base64 encoded data matters. So, we cannot just Base64 the search string and search for it if the encoded data starts on a different byte than the search string. So if we search for the string "Hello" and we encode from "H" as character 1 in the sequence of processing every 3 characters but the "H" appears at a character 2 position in the original to be searched text then it will not find it

So, if we want to find a clear string in a Base64 encoded text then we need to Base64 encode the search 3 times and use that for 3 searches of the original encoded string. If for instance we want to find the code "dbms_output.enable(1000000);" then we need three encoded strings

12312312312312312312312312312
dbms_output.enable(1000000);

1) dbms_output.enable(1000000) ZGJtc19vdXRwdXQuZW5hYmxlKDEwMDAwMDAp
2) bms_output.enable(1000000); Ym1zX291dHB1dC5lbmFibGUoMTAwMDAwMCk7
3) ms_output.enable(1000000 bXNfb3V0cHV0LmVuYWJsZSgxMDAwMDAw

The complete string is shown at the top as well as 123, 123 for character positions. The encoded version in the Base64 version we are searching could start on character 1 or character 2 or character 3. We therefore need 3 search strings Base64 encoded that are the maximum multiple of 3 characters we cab get out of the original string. You can see the 3 examples we have chosen and their Base64 versions. Interestingly you might question why we have "MDA" more than once or "MTA"; if you look at the original string this is easy to spot why...

Now we can use a simple search tool to search the original files and locate all of the instances of the string we would like to find.

Why are we interested in this?

What has this go to do with Oracle Security?

Well, I am doing it because I was asked to BUT there is a clear security angle and even an Oracle Security angle. Often an attacker of an application using or hosting an Oracle database might use Base64 or other techniques to hide or change their attacks strings for SQL Injection or other attacks. Sites often use security tools such as Intrusion Detection Systems (IDS) or Intrusion Prevention Systems (IPS) or.... The aim of the attacker is to trick these security systems and try and get past the rules and Base64 is a classic method to change the attack.

If you have logs for your database and application check for any Base64 encoded strings passed to the websites and check out what is in them, for instance search for common SQL Injection attacks. It can be useful to simply grep the Base64 data for known strings like we have exampled here rather then extracting potential Base64 and decoding it and then looking for strings.

#oracleace #sym_42 #oracle #database #security #base64 #sqlinjection #hacking #ids #ips #intrusion #detection

Write An Interpreter in PL/SQL - Adding More Features

Just a short post about the PL/SQL parser and interpreter that I have been developing.

As I have said in recent posts I am going to release a set of articles about the development of this interpreter in PL/SQL. I have over 120 pages of written notes and examples so far. As I said in the last post I will decide how to release these, either as about 15 - 25 blog posts or as articles indexed on my site; so not in the actual blog software but essentially the same; I may also release all of the notes as a short e-book on this website; not sure yet.

Of course, there are still features to add to the language and also to the interpreter and also to decide whether to convert it and also implement a compiler for the language and assembler and a CPU VM...

I have extended the language now so that it also has IF/ELSE/FI and also LOOP/EXIT/POOL keywords; so whist it can still support simple BASIC like syntax and GOTO and LABELs etc it is now easier to write programs without worrying about those GOTO and LABELs. The LABELs are now alpha as well so not :30 or :10 as in the previous examples. Also unlike BASIC we don't have a formal line structured program with a line number per line. We can also free form and indent the program structure as you will see in my examples.

I just wanted to show a quick couple of examples that tests IF statements and also the LOOP and EXIT statements. Here is a sample that tests and IF statement and a second that tests an IF/ELSE statement and a simple LOOP including an EXIT keyword.

Here is the simple example:

declare
lv_prog varchar2(32767):=q'[
LET m=20
LET x=1
LET y=1
IF x PRINT "x This should print "
PRINT "x---------------------"
FI
IF y>m THEN
PRINT "y This should not print"
PRINT "y----------------------"
FI
IF x PRINT "x1 This should print"
PRINT "x1---------------------"
ELSE
PRINT "x2 This should not print"
PRINT "x2---------------------"
FI
IF y>m THEN
PRINT "y1 This should not print"
PRINT "y1---------------------"
ELSE
PRINT "y2 This should print"
PRINT "y2---------------------"
FI
LET m=2
LET x=1
PRINT "Start of tests"
PRINT "=================="
LOOP
PRINT "x is [";x;"]"
IF x>m THEN
EXIT
FI
LET x=x+1
POOL
PRINT "End of Tests"
END
]';
begin
--
pfclscript.init(true,1);
pfclscript.run(lv_prog);
--
end;
/

And running this gives:

SQL> @interp
x This should print
x---------------------
x1 This should print
x1---------------------
y2 This should print
y2---------------------
Start of tests
==================
x is [1]
x is [2]
x is [3]
End of Tests

PFCLScript Execution Time (Seconds) : +000000 00:00:05.265551000
SQL>

This is a simple example of our language being interpreted and executed in PL/SQL. It is not blindingly fast as it took but that is fine; we have ways in the future we can speed this up by reducing the size of the script and also potentially reducing the size of the PL/SQL. We can work on performance of the interpreter after we are happy with its functionality.

Here is a second simple example in the script language that implements a nested loop in our language to print out a grid of numbers:

declare
lv_prog varchar2(32767):=q'[
LET m=2
LET x=1
PRINT "Start of tests"
PRINT "=================="
LOOP
LET y=1
LOOP
PRINT "x, y is [";x;",";y;"]"
IF y>m THEN
EXIT
FI
LET y=y+1
POOL
IF x>m THEN
EXIT
FI
LET x=x+1
POOL
PRINT "=================="
PRINT "End of Tests"
END
]';
begin
--
pfclscript.init(true,1);
pfclscript.run(lv_prog);
--
end;
/

Running this example shows:

SQL> @interp
Start of tests
==================
x, y is [1,1]
x, y is [1,2]
x, y is [1,3]
x, y is [2,1]
x, y is [2,2]
x, y is [2,3]
x, y is [3,1]
x, y is [3,2]
x, y is [3,3]
==================
End of Tests

PFCLScript Execution Time (Seconds) : +000000 00:00:11.041386000
SQL>

Whilst this is a shorter example than the first its slower at 11 seconds execution time as its more complex but it shows some great features of the language with a loop nested in another loop and two uses of IF/EXIT/FI to escape the loops. The PRINT statement with its dynamic parameter list is powerful where we can mix variables values and strings. This is similar in function but not syntax to the C language ... and things like printf()

The interpreter is around 850 lines of PL/SQL that implements some reasonable features of a programming language. I now call it PFCLScript rather than a simple version of BASIC; we can still write BASIC like code but now much better code.

I hope to get some speaking slots at conferences later this year and be able to demonstrate and show the design around this code.

#oracleace #sym_42 #oracle #plsql #secure #code #securecode #interpreter #vm #cpu #compiler #parser