Call: +44 (0)1904 557620 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.

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