EDITING BOARD
RO
EN
×
▼ BROWSE ISSUES ▼
Issue 33

Developing Secure Applications in Java

Silviu Dumitrescu
Line manager@Telenav



Diana Bălan
Map analyst@Telenav
PROGRAMMING

We will begin this article by some general considerations regarding security. Thus, the aim of computer security is to protect the information stored on them against theft, corruption or natural disasters while accessing it.

Security must be understood as a compromise solution. For instance, the best way to create a completely secure application on the Internet is not to connect it to the Internet.

One of the most important aspects of security is confidentiality, which represents hiding the information sources. The mechanisms used for ensuring confidentiality are: encrypting, using passwords and access control (giving access to resources to a limited number of people).

Another aspect is integrity, which means that the data is protected against unauthorized alterations. This is usually ensured by authentication. The user must provide credentials (username and password). Moreover, the detection systems should be used in case the authentication system fails. This system is made of access logs and analysis patterns.

A last aspect is availability, which represents the ability to use a system or a resource when needed.

The easiest way in which a system is vulnerable is represented by the attacks of denial of the services. They block the user's access to the system or reduce the performance level of the system. The system should be so flexible as to detect these attacks and respond to them.

Security aspects at software level

Any system containing private information is very likely to become a target for the attackers. Some of the fundamental concepts of security are:

Types of security threats

We can divide the threats into the following categories:

Injection and inclusion represent an attack which determines a program to interpret the data in an unexpected way. Therefore, any data coming from an uncertain source must be validated. The main forms of attack are:

The XSS vulnerabilities appear when:

The following example illustrates a XSS attack:

<%@page contentType=”text/html” pageEncoding=”UTF-8”%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=”Content-Type”
content=”text/html; charset=UTF-8”>
<title>Login Page</title>
</head>
<body>
<h2>Bine ati venit</h2>
<p>Va rog sa va logati</p>
<form method=”GET”
action=”/XssExample/ProcessForm”>
<b>Login Name: </b>
<input type=”text” size=”12”
maxlength=”12” name=”userName” />
<br/>
<b>Password: </b>
<input type=”text” size=”12”
maxlength=”12” name=”password” />
<br/>
<b>Locatia: </b>
<input type=”text” size=”12”
name=”location” /><br/>
<input type=”submit” value=”Submit” />
<input type=”reset” value=”Reset” />
</form>
<p><a href=”http://localhost:8080/XSS/ProcessForm?userName=Bob&password=Smith&location=</p>%3CScript%20Language%3D%22Javascript%22%3Ealert(%22Ai%20fost%20atacat!%22)%3B%3C%2FScript%3E”>Hacked URL</a></p>
<p>URL Script text: %3CScript%20Language%3D%22Javascript%22%3Ealert(%22vei%20fi%20atacat!%22)%3B%3C%2FScript%3E</p>
</body>
</html>

Respectively the servlet:

@WebServlet("/ProcessForm")
public class ProcessForm extends HttpServlet {
private static final long
serialVersionUID = -5014955266331211217L;

protected void processRequest(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println(
"<title>Login Page</title>");
out.println("</head>");
out.println("<body>");
out.println("<h2>Please login: </h2>");
out.println("<p>Please login: " +
request.getParameter("userName") + "</p>");
out.println("<p>Login Name: " +
request.getParameter("location") + "</p>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}

@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
public String getServletInfo() {
return "Servlet-ul meu";
}
}

SQL Injection is based on unfiltered data in order to alter the SQL results. Let's consider the following code:

ResultSet rs = stmt.executeQuery ("SELECT * FROM DEMO.Table1 WHERE NAME='" + nameParam + "' AND AGE ='" + ageParam + "'");

If the attacker sends: 'values' OR 'a' = 'a', it will make the selection predicate true, which is equivalent to:

ResultSet rs = stmt.executeQuery ("SELECT * FROM DEMO.Table1");

By doing this, the attacker can access private information or can even modify data in the data base. This is why any input must be filtered before being used.

OS command injection is based on unfiltered data which alter the command of the operating system. Let's consider the following example:

public class ListHomeDir {
  public static void main(String[] args) {
    String userName = "Silviu";
    String curLine = "";
      try {
    Process p = Runtime.getRuntime().exec(
      "cmd /c dir C:\\Users\\" + userName);
    BufferedReader stdInput = new 
          BufferedReader(new InputStreamReader(
          p.getInputStream()));

        BufferedReader stdError = new 
           BufferedReader(new InputStreamReader(
           p.getErrorStream()));

 System.out.println("Home directory is:");
 while ((curLine = stdInput.readLine()) != null) {
   System.out.println(curLine);
 }
 if (stdError.ready()) {
  System.out.println("error:");
 }
 while ((curLine = stdError.readLine()) != null) {
   System.out.println(curLine);
}
 System.exit(0);
} catch (IOException e) {
  System.out.println("exception: ");
  System.out.println(e.getMessage());
  System.exit(-1);
   }
 }
}

In the example, we wish to obtain a listing of a director. The attacker can send:

username;&& del *.*;, which can cause the loss of data.

Let's consider the following example of uncontrolled format of strings:

public class Main {
static Calendar c = new GregorianCalendar(1995, GregorianCalendar.MAY, 23);

public static void main(String[] args) {String param = "%1$tY";
        System.out.printf(param + "Error !!! %1$te \n", c);
    }
}

In this code, the programmer tries to print the results when two values do not match. The problem appears when a formed string is sent instead of a month. The attacker can figure out the year, for instance, when a card becomes out of date.

From the point of view of resource management, we have:

Let's consider the following example:

public class FileException {
    Properties appProps = new Properties();
    public static void main(String[] args) {
      FileException app = new FileException();
          app.readProps("AppConfig.properties");
      app.printProps();
    }

    public void readProps(String fileName) {
    try {
     appProps.load(new FileInputStream(fileName));
     } catch (IOException e) {
    System.out.println("Cannot find the file "+ 
      "de configurare: " + e.getMessage());
    e.printStackTrace();
    System.exit(-1);
    }
     } 
  public void printProps() {
    appProps.list(System.out);
  }
}

The system should not provide the potential attackers with the exact location of the configuration file of the application.

Confidential information should be available to reading only in a limited context; they should not be available for manipulation; users should be provided only with the information they need; the information should not be hard coded in the sources.

Private data should not be included in exceptions of log files. Also, we shouldn't hard code the username and password into the source code. We should use an attributes file in order to store this type of information.

Here is an example of creating and using a log file.

public class BasicLogging {
    Logger logger = Logger.getLogger("com.example.BasicLogging");

    public void logMessages(){     
        logger.severe("Critical error");
        logger.warning("Advertisment");
        logger.log(Level.INFO,"Usefull info");
        logger.config("Info about CONFIG");
    }

    public static void main(String[] args) {
        BasicLogging bl = new BasicLogging();
        bl.logger = Logger.getLogger("com.example"+
    ".BasicLogging");

        try {
         bl.logger.addHandler(new FileHandler(
          "Basic.log"));
            bl.logger.setLevel(Level.INFO);
            bl.logMessages();
        } catch (IOException e){
            e.getMessage();
        }
    }
}

We hope you have enjoyed reading this article and we are looking forward to your questions!

Conference

Sponsors

  • ntt data
  • 3PillarGlobal
  • Betfair
  • Telenav
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • UIPatj
  • MetroSystems
  • Globant
  • Colors in projects