Friday 27 February 2015

snLibrary - Encryption & Decryption - Inter-Application Communication

snLibrary - Encryption & Decryption
(v10.2 dtd. 07-Dec-2010)

Until the advent of CAS (Central Authentication Service), authentication used to be done at the application level by prompting the user for a User-ID and a Password.  Those parameters are then compared with that stored in the database inorder to assertain whether or  not to allow the user to proceed with operating the application.

There are two methods of verification of password. For example.
Eg. 1:-
a. Obtain the password from the user
b. Verify whether the password entered is the same as that in the database table by comparing the obtained password with the decrypted password obtained from the table (assuming that the password has been stored in the encrypted form in the table).
c.  If the password entered and the password decrypted are the same, allow to proceed with the application; otherwise not.


Eg. 2:-
a. Obtain the password from the user.
b. Encrypt the password obtained from the user.
c. Verify whether the encrypted password entered is the same as that stored in the database table, by comparing both of them.
d. If the passwords match, allow to proceed with the application; otherwise not.

In my opinion, the second is the better method as it is more secure.  Further security can be ascertained by the following form of the SQL.
query = "SELECT userid, userpswd FROM USER_TABLE where userpswd = ?  and userid = ?";
pS = con.prepareStatement(query);

pS.setString(1, user_id);
pS.setString(2, snPassword.getInstance().encrypt(password));
pS.executeQuery();

Having obtained the result set after executing the SQL, once again verify the userid and userpswd with that obtained.
       if (userid.equals(rs.getString(1)) && userpswd.equals(rs.getString(2))) {
            // proceed further on with the application 
       } else {
          // throw Error in User Id / Password 
       }
It is advised to never use any of the following SQLs for application security reasons as they are prone to bugs/SQL injections:
query = "SELECT * FROM USER_TABLE WHERE userid = '" + user_id + "' and userpswd = '" + password + "'";

query = "SELECT 1 FROM USER_TABLE WHERE userid = '" + user_id + "' and userpswd = '" + password + "'";

query = "SELECT userpswd FROM USER_TABLE WHERE userid = '" + user_id + "' and userpswd = '" + password + "'";



snPassword.getInstance().encrypt(password) was specifically written incorporating base64 algorithm for encrypting a string.  However, the decryption is cumbersome and therefore, comparison of passwords are not made by decrypting the stored value of the password; rather is done by encrypting the input password using the same method and comparing the encrypted password with that stored in the database table.

For better standards, no decrypt method was provided in the snPassword class so that coders would it only as an ecrypting tool and not for decrypting.

However, later on (around Dec. 2010), requirement came in for having a decrypting algorithm.  I had in 1998 - 2000 an algorithm developed for an Imprest Module that was written in PowerBuilder and worked well.  Therefore, the same algorithm was copied into a new Java class called snEncryption.

This class provided encrypt() and decrypt() algorithms.  However, what I like most about this class is an additional feature that you might not see many-where!!.

The feature was developed in response to a requirement of communicating securely between applications on HTTP.  In the normal course, if we need to communicate between applications, say call an http page from one application to another, we could just pass it on creating a URL with the & delimiter joining the various parameters being passed.  How then, is it possible that the receiving application understands that the requesting URL is not arriving from any hacker trying to get some sensitive details?  In such a case, the following technique can be used.

This interesting feature can encrypt a URL with its parameters and send to another web-application.  The receiving web-application should have included a small filter inside its WEB-INF/web.xml that would ensure that the original parameters are received by the appropriate servlet. The feature is enriched by the fact that the life of the URL is not more than (default) 180 seconds.

Needless to say, that this methodology, can also be adopted as an internal security feature wherein, referring URLs within the same application could also be done with this alone.

Let me show you the implementation.
Dispatching Web Application:
File:-myURLDispatcher.jsp
<%@page import="config.snEncryption" %>
// ...
// ... Some part of the Servlet Code goes here 
// ...
<%
String param = "myparam1=First Param&myparam2=Second Param&noparam=No Param&userid=Kavya";
snEncryption snE = new snEncryption(param.length());
String encryptedParam = snE.encryptURLtoURLParam("NewServlet?", param, null, true);  
// Null is default value for UTF-8 encoding with default TTL (Time To Live) of 180 seconds
//            -or-
//  String encryptedParam = snE.encryptURLtoURLParam("NewServlet?", param, null, true, 120);  
// Last parameter indicates TTL of 120 seconds instead of default 180 seconds.
%>
  <form name=form1 method=get action=<%=encryptedParam%>  >
      <input type=submit value=Submit />
  </form>

Note:-  The NewServlet.java would use the request.getParameter("userid") to get the value "Kavya", use request.getParameter("myparam1")  to get the value "First Param" etc.  In other words, there is no need for decrypting the URL in the receiving servlet because, the decryption algorithm is taken care of by the Filter.

File:WEB-INF/web.xml 
<filter>
<filter-name>Induce Params Screen Approver</filter-name>
<filter-class>
org.sun.raibmanus.filters.snInduceParamsScreenApprover</filter-class>
    <init-param>
      <param-name>exclude_url-2</param-name>
      <param-value>/folder/index_[3-5].jsp</param-value>
    </init-param> 
    <init-param>
       <param-name>exclude_url-4</param-name>
       <param-value>([\w||\-||/])+\.([gG][iI][fF]|[pP][dD][fF]|[pP][nN][gG]|[jJ][pP][gG]|[jJ][pP][eE][gG]|[bB][mM][pP]|[jJ][sS]|[cC][sS][sS]|[sS][wW][fF]|[iI][cC][oO])</param-value>
    </init-param>        
    <init-param>
      <param-name>include_url-2</param-name>
      <param-value>/folder/index_4.jsp</param-value>
    </init-param> 
</filter>

<filter-mapping>
<filter-name>Induce Params Screen Approver</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


Apart from encryption, this filter also allows including in all the Http requests, persistent  request parameters that are stored in the snConfigFile.  For example, suppose the following should be a forced parameter in all requests of my web-application which I could use the getParameters() method to access, we may define them in the snConfigFile as below.
File:=c:/snConfig/snConfigMyApplication.ini
Persistent Request Parameter-name=Suresh Nambiar
Persistent Request Parameter-userid=Jack
Persistent Request Parameter-pwd=password233453
Persistent Request Parameter-Pwd=sureshpassword

What this means is that along with each and every request coming into the web-application server, the above four parameters would also get appended.  The four parameters in this case are 'name', 'userid', 'pwd' and 'Pwd'.

If org.sun.raibmanus.filters.snInduceParamsScreenApprover is used for the filter, the received parameters if any, are also included along with the Persistent Request Parameters.  Whereas in the case of org.sun.raibmanus.filters.snIncludeParamsFilter, no existing values other than those sent as encrypted using snEncryption..encryptURLtoURLParam() & the Persistent parameters are included. (org.sun.raibmanus.filters.snIncludeParamsFilter is deprecated.)

Yet another improved version (version 11.1 dtd. 24th Dec. 2010) has additional features viz. removing from response content, remove certain content types from the response text like patterns that contain 'xml', 'text', 'text/html' etc.  org.sun.raibmanus.filters.snInjectedParamsResponsePatternModifier can be used as the filter in-lieu of the above mentioned snIncludeParamsFilter.  

If the snInjectedParamsResponsePatternModifier is used, the filter shall be as follows:

File:-WEB-INF/web.xml 
<filter> 
<filter-name>Injected Params Response Pattern Modifier</filter-name>
<filter-class>org.sun.raibmanus.filters.snInjectedParamsResponsePatternModifier</filter-class>
<init-param>
<param-name>ModifyRequestQueryString</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>RemoveFromResponseContent</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>ContentTypeforRemoveResponse-1</param-name>
<param-value>text/html</param-value>
</init-param>
<init-param>
<param-name>ContentTypeforRemoveResponse-2</param-name>
<param-value>text</param-value>
</init-param>
<init-param>
<param-name>ContentTypeforRemoveResponse-3</param-name>
<param-value>xml</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Injected Params Response Pattern Modifier</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

And in the snConfigFile, the entry should be as follows:
File:- c:/snConfig/snConfigMyApplication.ini
Persistent Request Parameter-name=Suresh Nambiar
Persistent Request Parameter-userid=Jack
Persistent Request Parameter-pwd=password233453
Persistent Request Parameter-Pwd=sureshpassword

#Response Content Search Pattern=http//
#Response Content Search Pattern=viewer/viewframeset/
Response Content Search Pattern=.*

#Response Content Replace Pattern==[^&]*&?
#Response Content Replace Pattern==[a-e]*
Response Content Replace Pattern==[^&]*&?\s

Note that there can only one Content Search and Replace Pattern. Only the last valid entry (ie. without the starting # mark) would prevail.

With snLibrary version 11.1,  org.sun.raibmanus.filters.snIncludeParamsFilter,  org.sun.raibmanus.filters.snInduceParamsScreenApprover  etc. have been deprecated.

Note:- The 'Response Content Search Pattern' + 'Response Content Replace Pattern' work together and is operational if and only if RemoveFromResponseContent is set to 1 in the initparam. In which case, the response data is filtered and replaced by the pattern specified.

There is an incredible story behind providing this feature.  We had a reporting software called 'Actuate'.  It works on a Tomcat web-server providing compiled reports.  The required reports are compiled in the night and posted for ready availability giving the impression of a fast retrieval thereby improving user-experience.  For making the reports available to the internet, the Actuate server was put on NAT (Network Access Translation).  Once, it so happened that some('one') from the internet world (China or Korea...) hacked-in and deposited a bot into it.  It was then decided that some security needs to be improved on the Actuate server as it was exposed to Public IP addressing. Therefore, I suggested to put the Actuate server behind the reverse proxy and started exploring the source codes.  One day, I was examining the source of the response received from the Actuate server when to my surprise, found that the User-ID  as well as the password was being thrown down to each page as a hidden input field so that every further request could carry it along and get authenticated at the Actuate Server.  (Let me tell you, that day I was shocked to see the poor Code Quality that was unexpected but exhibited promptly, by well known and established Multi-National Companies like the one that was examined).  It was further surprising to find that it was the Admin user id with all authorities & rights along with its password for the Actuate Server that was so foolishly exposed and communicated as response data to the client!!.  I immediately alerted the team responsible for hosting the Actuate Server.  This has however, now resulted in a better configuration with the response being camouflaged (at least) to keep away not-so savvy ones from peeping into the Actuate Server - though definitely neither the amateur nor the experienced hackers.

I wanted to do something for this cause and therefore, included this specific Filter mentioned above that would pickup the user id and password from the Actuate Server itself (as Persistent Request Parameters) while not sending the values back to the client (by filtering them out through the 'Response Content Search Pattern' + 'Response Content Replace Pattern' combination).

The last part would ensure that you do get cleaner response data with some sort of filter applied.  Such are usually useful in AJAX responses and ensuring accuracy in or validating  the response at the server side itself.

No comments:

Post a Comment