bookmark_borderPaypal, vulnerability through obscurity?

I have been member of Paypal for quite some time, and I use it rarely.

When I use it, I want it to be a quick, seamless experience. I log in, do my business, log out. Thats it.

Reality is different. Although I must admit, it does not help that I forget my password every time. Since I use Paypal every 6 to 12 months I can’t get it in my muscle memory.

I bought 1password a while back to help me remember only one password (you don’t say?) and let it generate strong, secure passwords. I have been changing my passwords on all websites I visit ever since.

And so Paypal and I meet again. And I want to change my password.

The last time I wanted to change my password at Paypal it was a very, very unpleasant experience. I actually was glad I got through the process and wanted to forget about it. This time I decided to write about it because it is a long while back and it really is bad.

In a sense you could say Paypal has been compromised, not technically but through usability.

Before I could change my password I had to answer my security questions which I filled in whaaaay back and I could hardly remember them. Since I did know the answer of the security question but I could not write the down *exactly* I had a hard time getting past the first step. So I get it, you want to protect us from others changing our password when we forgot to log out and such. Why not ask the password *again* (old password) at this very step? (This step did not happen after I wanted to change my password again, so it is as if this is into effect when the user has not logged in for a while.)

Once I got past the ‘security questions’ page I actually get the familiar 3 fields: old password, new password and new password again.

I open 1password, let it generate a strong password and then I got smacked in the face again. You may not copy and paste a password in the ‘new password’ fields. Paypal deliberately blocks any copy/paste actions.

We’re not finished though, because Paypal is also very specific about what your password may or may not be.

– It may not contain your name or email address (which makes sense)

– It must contain a symbol, a number and a capital. Even though it does not even matter for your password strength. (it is not like computers actually *read* your password as humans do)

– It has a maximum length. What!? Got worried passwords take up too much space? I can’t possibly imagine why you would restrict this.

– Your password should be hard to guess for a relative or friend. (which kind of infers the 1st point)

Since I cannot copy/paste the password, I have to copy/paste the password in an editor. Re-arrange my windows so I can fill in my password and see it at the same time. After I filled the first new password field, I actually get a warning that my password is at maximum length. As if it is a bad thing my password is 20 characters long.

I go on, type the password again and (of course) I made a mistake (typo), which results in a red message saying the passwords are not the same.

So here I am, trying to change my password and about to give up because it is as if Paypal does not want me to have a secure account.

I believe we got here a ‘we think too much for the user’ syndrome. I believe Paypal does want their users to have secure accounts (the what part), but how they implemented it is having an opposite effect (at least on me). So how could they have done it better?

– get rid of the security questions first (*)

– don’t restrict maximum password length, keep your minimum. Seriously, there is no reason to do this.

– don’t enforce special symbols, capitals or numbers. Instead hint them how to create easy to remember yet very strong passwords.

– allow copy and pasting. If you are afraid of some users being compromised by that, then they probably are being compromised on several levels.

And perhaps the most important suggestion: Make it an easy, seamless and effortless to change your password.

(*) – Yes, this might indicate that if someone knew my password they could change it, which perhaps the security questions wanted to prevent. However, if someone knew my password then that is a problem on itself. And you’re probably trying to fix the wrong problem.

bookmark_borderPrevent cross-site scripting when using JSON objects using ESAPI and Jackson framework 1.7.x

Recently I have had the opportunity to fix a cross-site-scripting problem.

The problem: a lot of JSON objects are being sent over the wire and the data is not being html escaped. This means that anyone who would put html data IN would get it out and make any user vulnerable for XSS attacks.

In this case, JSON objects are being created by using the MappingJacksonHttpMessageConverter. This is deliverd by the Spring framework. Normally it is instantiated when you use spring-mvc (using the mvc-annotation tag). This allowed us to just return an object and the MappingJacksonHttpMessageConverter would take care of translating it into a JSON object.

In order to influence the creation of the JSON object and make it encode HTML for String values we need to do a few things:

  1. Create a Custom Object Mapper and wire into Spring
  2. Create a JsonSerializer that encodes HTML (using ESAPI)
  3. Register the JsonSerializer in the CustomObjectMapper

Create a Custom Object Mapper and wire into Spring

However, now we want to change the value serialized by the MappingJacksonHttpMessageConverter. So how do we do that? The MappingJacksonHttpMessageConverter uses an ObjectMapper. So in order to get the ObjectMapper map the values to an encoded one we need to create a custom Object mapper.

public class CustomObjectMapper extends org.codehaus.jackson.map.ObjectMapper {
}

At first we leave it empty. We want to make Spring make use of our CustomObjectMapper first. In order to do that you need to write out the mvc-annotation tag, because we need to inject our CustomObjectMapper in the the MappingJacksonHttpMessageConverter. This is a bit difficult to figure out at first, but for your convinience I have proveded the configuration you need.

<bean id="CustomObjectMapper" class="your custom object mapper"/>

<bean id="MappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
	<property name="objectMapper" ref="CustomObjectMapper"/>
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	<property name="order" value="1" />
	<property name="customArgumentResolver" ref="sessionParamResolver"/>
	<property name="webBindingInitializer">
	<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
		<!-- <property name="conversionService" ref="conversionService" />  -->
		<property name="validator" ref="validator" />
	</bean>
	</property>
	<property name="messageConverters">
		<list>
			<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
			<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
			<bean class="org.springframework.http.converter.ResourceHttpMessageConverter" />
			<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
			<ref bean="MappingJacksonHttpMessageConverter"/>
		</list>
	</property>
</bean>

As you can see, the AnnotationMethodHandlerAdapter is the bean where everything is getting wired into. The messageConverters property contains a list of converters. The last entry is where the MappingJacksonHttpMessageConverter is referenced. Normally it is defined like the beans above it. But since we want to inject our own CustomObjectMapper it is done this way.

Create a JsonSerializer that encodes HTML (using ESAPI)

Now we know our CustomObjectMapper is used, we can start the part where we want to influence the way the jackson framework serializes our objects to JSON. In order to do that we create our own JsonSerializer. Then, we override the serialize method and make sure the provided jsonGenerator is writing our encoded value.

Code:

public class JsonHtmlXssSerializer extends JsonSerializer {

   public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
      if (value != null) {
         String encodedValue = encodeHtml(value);
         jsonGenerator.writeString(encodedValue);
      }
   }

}

So this class extends from org.codehaus.jackson.map.JsonSerializer, and implements its own serialize method. The method encodeHtml will use the ESAPI encoding functions to escape HTML.

 

Implementing this is very easy:

   protected String encodeHtml(String html) {
      DefaultEncoder encoder = new DefaultEncoder();
      return encoder.encodeForHTML(html);
   }

The defaultEncoder is from ESAPI allowing us to encode the HTML.

 

Register the JsonSerializer in the CustomObjectMapper

The final step is to register the JsonSerializer within the ObjectMapper used by Spring. Doing that using Jackson 1.7.0 is very easy. Using the provided SimpleModule class we can easily add our own Serializer to the ObjectMapper. We do that by creating our own default constructor, which will register our serializer. Like so:

@Component
public class CustomObjectMapper extends org.codehaus.jackson.map.ObjectMapper {

   public CustomObjectMapper() {
      SimpleModule module = new SimpleModule("HTML XSS Serializer", new Version(1, 0, 0, "FINAL"));
      module.addSerializer(new JsonHtmlXssSerializer());
      this.registerModule(module);
   }
}