Sunday, January 19, 2014

No sign of vulnerability on authentication module done using Servlet

Actually I was trying to discover the CSRF thing happened on the web app. I'm trying to find out this vulnerability through ZAProxy to understand the real fact happens behind the scene. To do this, I made an web app that purely done using Servlet, not involving any JSP. This Servlet program allow users to authenticate themselves before render the protected resource.

This is the Servlet configuration in Deployment Descriptor:
 <servlet>
   <servlet-name>TestServlet</servlet-name>
   <servlet-class>org.huahsin.TestServlet</servlet-class>
 </servlet>
  
 <servlet-mapping>
    <servlet-name>TestServlet</servlet-name>
    <url-pattern>/test</url-pattern>
   </servlet-mapping>
  
   <security-constraint>
    <web-resource-collection>
     <web-resource-name>Wildcard means whole apps requires authentication</web-resource-name>
     <url-pattern>/*</url-pattern>
     <http-method>GET</http-method>
     <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
     <role-name>tomcat</role-name>
    </auth-constraint>
    <user-data-constraint>
     <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
   </security-constraint>

 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>
public class TestServlet extends HttpServlet {
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out.println("This is a Test Servlet.");
  
  Enumeration headerNames = request.getHeaderNames();
  while( headerNames.hasMoreElements() ) {
   String headerName = (String) headerNames.nextElement();
   out.println("Header Name: < i >" + headerName);
   String headerValue = request.getHeader(headerName);
   out.println("< /i >, Header Value: < i >" + headerValue);
   out.println("< /i >");
  }
  
  out.println("< hr / >");
  
  String authHeader = request.getHeader("authorization");
  String encodeValue = authHeader.split(" ")[1];
  out.println("Base64-encoded Authorization Value: < i >" + encodeValue);
  String decodeValue = Base64.base64Decode(encodeValue);
  out.println("< /i >Base64-encoded Authorization Value: < i >" + decodeValue + "< /i >");
 }
}
The users are define in Tomcat server, when the page launch, a prompt to user to enter a valid login credential in order to view the content. Unfortunately ZAProxy not able to do any test on it as it doesn't contain any JSP page. Since ZAProxy couldn't run any test on it, I move on to plan B. This time I create a JSP page, this JSP will replace the server authentication:
 <form action="login" method="POST" name="loginForm">
Username:<input name="txtUserName" type="text" value="" />
  Password:<input name="txtPassword" type="password" value="" />
  <input type="submit" value="login" />
  <input type="reset" value="clear" />
 </form>
Next thing is to remove the <security-constraint> from Deployment Descriptor to get rid of server authentication and allow user to authenticate through a web page. That's all about the change. When I run the test again on ZAProxy, there is no sign of vulnerability found on this example, I think I need to move on to bigger challenge to realize CSRF thing.

Saturday, January 18, 2014

How to configure Tomcat to support JEE6?

I have a servlet program create under Tomcat 6 environment, I found it interesting there was an error on login() and logout() as these methods are undefined.
protected void processRequest(HttpServletRequest request, HttpServletResponse response) {
    ...
    request.login(userName, password);
    ...
    ...
    request.logout();
}
As I check in the documentation in JEE6, the login() and logout() was there but not in JEE5. I did a check on the project facet in Eclipse IDE, the project was using Dynamic Web Module 2.5 and Java 1.6. Can I conclude that my tomcat is actually working with JEE5? I am so curious what else did I miss configure in order to support JEE6?

As I did a deep search, this can not be done. Why? Because Tomcat isn't an enterprise server. I found the clue from here. To proof me right, I run quick test on WAS Liberty Profile and Tomcat EE by configuring the target runtime in Eclipse IDE. Both of them compile without any error. Cheers!

By the way, I though I suppose to aware of this since I have been doing enterprise software for 3 years?

Tuesday, January 14, 2014

Is it possible to make a standalone application with Maven?

Hey, I've been using Maven on web application project for most of the time, ever wonder could it be done on standalone project? The answer is yes. Make a quick search on Google, this tutorial will shows up. But that is a little bit too complicated. Can it be a little more easier? The answer is yes. (Sorry, I'm a lazy programmer.)

When launching a new Maven project, filter with maven-archetype-quickstart in the Archetype selection dialog box, pick that one and follow the instruction all the way down. A standalone project without web stuff in the project setting will be ready to accept new code.

Next question is how could I run it? This is what I have been done on my POM.xml:
  <build>
   <pluginmanagement>
    <plugins>
     <plugin>
      <groupid>org.codehaus.mojo</groupid>
      <artifactid>exec-maven-plugin</artifactid>
      <version>1.2.1</version>
     </plugin>
    </plugins>
   </pluginmanagement>
   
   <plugins>
    <plugin>
     <groupid>org.codehaus.mojo</groupid>
     <artifactid>exec-maven-plugin</artifactid>
     <version>1.2.1</version>
     <executions>
      <execution>
       <goals>
        <goal>exec</goal>
       </goals>
      </execution>
     </executions>
     <configuration>
      <mainclass>org.huahsin.Selenium2.App</mainclass>
     </configuration>
    </plugin>
   </plugins>
  </build>
In Eclipse Maven goal, put package exec:java to launch the standalone application. Take note there are some details on the exec command, read it from here.

Selenium not navigate to given URL

What a silly day for me! I was setting up a Selenium project using Maven in Eclipse IDE, somehow the browser was launched but not navigating to the given URL. It just showing blank screen after launched.

Remember in some years back, I have encountering this issue before but this problem is due to the network was behind a proxy server. Since I'm doing it at home, I'm sure I don't have any proxy server setup. I give up to do it on Maven, make it a traditional project, import the Selenium JAR manually. It works! (What a joke!)

I spend my whole day looking at the source code, searching for the root cause then only I find out it is actually cause by the Maven configuration. Code snippet below shows the original Maven configuration:
  <dependencies>
    <dependency>
      <groupid>junit</groupid>
      <artifactid>junit</artifactid>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
     <groupid>org.seleniumhq.selenium</groupid>
     <artifactid>selenium-remote-driver</artifactid>
     <version>2.33.0</version>
    </dependency>
    <dependency>
     <groupid>org.seleniumhq.selenium</groupid>
     <artifactid>selenium-firefox-driver</artifactid>
     <version>2.33.0</version>
    </dependency>
  </dependencies>
See that the Selenium version number was set to 2.33, have a check on the Selenium site (as of this writing), the latest version was 2.39. To conclude this, using the wrong version may cause the Selenium not navigate to the given URL.

Friday, January 10, 2014

A good design in classes could make Mockito happier

I am having difficulty on executing a unit test that will throw ClassNotFoundException when an error has occurred. But later I found out that this difficulty isn’t come from the limitation of the test framework (Mockito or PowerMock) but it is due to the design problem in my class. I think I should aware of this problem during the development stage but why I only see it during unit test stage? Not only this design is impractical but it also makes the unit test execution even harder. Consider the following scenario, I have initConnection() declared in base class, and this method is invoke from the subclass:
public abstract class ReportService {

 ...
 ...

 protected void initConnection() {
  try {
   ...
   ...

  } 
  catch(HibernateException e) {
   e.printStackTrace();
  } 
  catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

public abstract class HibernateReportService<T> extends ReportService {

 ...
 ...

 public void execute() {
  
  try {
   initConnection();

   ...
   ...
  }
  finally {
  }

 ...
}
Assuming I want to verify ClassNotFoundException is thrown when an error has occurred. If I initiate the test execution using following code snippet, this will cause the test failed because the exception has been caught in base class.
 @Test(expected=ClassNotFoundException.class)
 public void testInitConnectionClassNotFoundException() throws Exception {
  ...
  ...
Suddenly, my mind raise up a very interesting question to me, am I doing the thing right? Am I coding the right thing? According to the best practices, I should not catch the exception in base class whereas I should escalate to the subclasses to handle the exception. By following this design, changes were made on the base code, initConnection() will no longer catching any exception:
 protected void initConnection() throws ClassNotFoundException {
  ...
 }
When I execute the unit test code above, the test was finally passed. Something has been clear in my mind now, during Whitebox testing, the test is not to check whether the exception has been handles properly but to verify what will be the behavior if an exception has been thrown. Put in other words, exception must throw during Whitebox testing. When handover to test team, then only tester will need to verify those exceptions being handles properly through a series of black box testing, not during Whitebox testing.

Thursday, January 9, 2014

Impractical use of doCallRealMethod() when object being spy

Oh no! Another mistake in this morning. Although the code sound true but the code doesn't sound logic. Take a look at the code snippet from previous note as an example:
public class FileClass {
 public void funcB() {
  
  try {
   throw new ClassNotFoundException();
  }
  catch( ClassNotFoundException e ) {
   ...
  }
 }
}
Due to the misunderstanding between mock and spy, the following test code isn’t really practical because ClassFile is already in spy mode, the use of doCallRealMethod() is just a waste, thus invoking the real instance is more than enough. doCallRealMethod() is usable if and only if FileClass is a mock.
 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  Mockito.doCallRealMethod().when(fc).funcB();
  fc.funcB();
 }

Wednesday, January 8, 2014

Invalid use of doThrow() with spy object

Things happened in this morning really embracing me. I’ve made a huge mistake in my programming life because I was confuse on the usage between Mockito.spy() and Mockito.mock().
public class FileClass {
 public void funcB() {
  
  try {
   throw new ClassNotFoundException();
  }
  catch( ClassNotFoundException e ) {
   ...
  }
 }
}
Suppose I have the above class ready for unit test, take note that I have try...catch surrounding the throw statement. My objective is to test whether ClassNotFoundException will be thrown when funcB() is invoke. If I execute the unit test code below, the test will fail with java.lang.AssertionError: Expected exception: java.lang.ClassNotFoundException.
public class TestMainApp {

 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  fc.funcB();
 }
}
The result of this test was actually fail. The reason being why this test was failed is because the throw statement in funcB() has already been catch. Since the exception has already catch, there were no more exception being escalate from funcB() when the control return to testFuncB(). In order to make this work, I think of a workaround solution. I modify the test code to mimic the ClassNotFoundException is being thrown:
 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  
  Mockito.doThrow(new ClassNotFoundException())
  .when(fc).funcB();
  
  fc.funcB();
 }
Smart right? NO! This code has actually cause the unit test run even worst. Now I can see MockitoException shown in the stack trace:
java.lang.Exception: Unexpected exception, expected but was
 ... 
 ... 
 ... 
Caused by: org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: java.lang.ClassNotFoundException
 ... 
 ... 
This is a big mistake. Whenever the class is under test, never mock on the class, just invoke the real instance. Put in the practical way, the use of doThrow() is invalid here because I’m not doing any mock on FileClass. Never think of remove the surrounding try...catch block because this has violated my original design even though it’s working fine.

Saturday, January 4, 2014

Invoke protected method with PowerMockito

My objective is to invoke the real execution of a method during the unit test. The hardest part on running this unit test is I'm targeting on a protected method. Mockito couldn’t do well with this, but PowerMockito do provide a very good solution on private/protected method. Following scenario shows how the existing classes were designed, and the target method that I’m going to unit test is initConnection().
public abstract class ReportService {

 ...

 protected void initConnection() {
  try {
   Class.forName("com.informix.jdbc.IfxDriver");
   
   session = HibernateUtil.currentSession();
   session.beginTransaction();
  } catch(Exception e) {
   e.printStackTrace();
  }
 }

 ...
}

public abstract class HibernateReportService<T> extends ReportService {

 ...

 public void execute() {
  
  try {
   initConnection();

   ...
   ...

}
To achieve my objective, there are 2 possible ways for the setup in my stub code. It is either Method 1:
 public void initConnectionCallRealMethod() throws Exception {
  PowerMockito
   .when(this.daoReportService, PowerMockito.method(ReportService.class, "initConnection"))
   .withNoArguments()
   .thenCallRealMethod();
 }
Or Method 2:
 public void initConnectionCallRealMethod() throws Exception {
  PowerMockito.doCallRealMethod()
   .when(this.daoReportService, PowerMockito.method(ReportService.class, "initConnection"))
   .withNoArguments();
 }
}
this.daoReportService is an instance of object that extends from HibernateReportService which is being spy. And also notice the use of PowerMockito.method(), this is due to the reason initConnection() is not visible to the outside world, thus the regular use of when() will not going to work.