Some time ago I demonstrated the Honeypot Project at Teched, and during one of the Bird of the feather sessions I displayed the code. It was the result of a port from Coldfusion and PHP scripting to BSP code. In this series of web logs I will explain how things are done in order to obtain the same functionality as their counterparts. I won’t bother going into detail for the obvious things but only for the tasks which were a challenge.
One of the tasks in such a honeypot is to retrieve the code and send the hash to the honeypot server in order to determine whether anything malicious has happened to the honeypot and whether any code has been changed. As such it shouldn’t be a big problem to achieve this, weren’t it for the fact that the programming environment is totally different. Whereas scripts in PHP and Coldfusion reside on the file system, BSP scripts reside in a database. A different approach is therefore needed for retrieving: opening a file vs. retrieving the BSP page from the database. Here’s an overview of the things that need to be done. I’ll also elaborate on how to hash the script afterwards.
First of all we need to retrieve the name of the BSP application
p_key-applname = runtime->application_name.
Then we need to know the name of the page.
p_key-pagekey = runtime->page_name.
Why do we need to do this? Well the script is generated by the honeypot server and as such the script doesn’t know what the name of the application or the BSP page is. So one should hard code that manually. But that would have as an effect that the page would be “changed” and the honeypot server would not be able to determine whether the modifications were malicious or not. The solution for that is to let the page itself determine how it’s called and where it resides.
Then we need to put things in uppercase before calling the next method.
translate p_key-applname to upper case. translate p_key-pagekey to upper case.
We load the data of the whole BSP page based on the p_key. p_key has the type o2pagkey
call method cl_o2_api_pages=>load_with_access_permission exporting p_mode = 'SHOW' p_pagekey = p_key p_version = 'A' importing p_page = p_data exceptions others = 1.
The result is store in p_data defined as type ref to cl_o2_api_pages.
We are only interested in the layout, since there is nothing in either the event handler or attributes. The reason for this is that the honyepot should be copy/paste and no other things should be involved except transporting and making the BSP app public available.
CALL METHOD P_DATA->GET_PAGE IMPORTING P_CONTENT = l_layout EXCEPTIONS others = 1.
The next step is to calculate the hash of it. Before we can do this, we need to eliminate all the non (alpha)numeric characters. This can easily done with regular expressions (see The regular express web log for more info). If you don’t have the chance to be working on a NW2004s, you will have to do it the tedious way, meaning looping over the string and checking whether the character is contained in the list of all (alpha)numeric characters.
clear hashstr. LOOP AT l_layout into wa. origStr = wa-LINE. clear newStr. WHILE origStr IS NOT INITIAL. IF origStr(1) CA '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. CONCATENATE newStr origStr(1) INTO newStr. ENDIF. origStr = origStr+1(*). ENDWHILE. concatenate hashStr newStr into hashStr. endloop.
The result string can now be hashed. That looks simpler at first sight than it is in reality. ABAP has standard MD5_CALCULATE_HASH_FOR_CHAR, which doesn’t work properly in our case, due to the parameters of this FM. After some reverse engineering, research and a favourable wind in SDN, the FM CALCULATE_HASH_FOR_CHAR came as a solution.
CALL FUNCTION 'CALCULATE_HASH_FOR_CHAR' EXPORTING ALG = 'MD5' data = hashStr IMPORTING HASH = hash EXCEPTIONS UNKNOWN_ALG = 1 PARAM_ERROR = 2 INTERNAL_ERROR = 3 OTHERS = 4.
Bear in mind that OSS says the following about this FM: ‘Please be aware that this function module has not been released for customer use. Therefore its use with non-sap code is not supported.’