During a PA-DSS audit process it was found credit card number in our server side code (process memory dump) after running a credit card payment transaction.
I have tried initially just invoke JVM garbage collector at the end of the payment transaction since our variables were local to solve this problem. But there is still a single instance referring to a credit card (CC) in the memory dump. This CC string (actually it was a byte[]) was referenced by SOAP CXF client object that was using internally sun.net.www.protocol.https.HttpsClient that was finally using BufferedOutputStream object.
Looking at code for BufferedOutputStream I have noticed the private flushBuffer() method was just setting the count variable to zero and not resetting the internal byte[] array.
No problem in this code for regular app (just reset count variable is simpler and efficient) but this raised a flag in our secure audit process so my alternative was to create a custom java.io.BufferedOutputStream that it would reset to zero this byte array and then I would need to add this file in the tomcat boot classpath.
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
//NEW - Custom code to reset buffer
for (int i = 0; i < count; i++) {
buf[i] = 0;
}
//End custom code
count = 0;
}
}
This actually worked and I could not find the CC data in the memory dump anymore but I don't feel this is the correct solution (custom change of a java core class).
Any suggestion how I could address this problem in a different way (w/o having to change any library code) ?
Java allows you to extend libraries without "having to change any library code". You can extend BufferedOutputStream to make SecureBufferedOutputStream, which will zero the contents of the buffer after a flush and before garbage collection (in case your JVM implementation doesn't already zero garbage collected memory).
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
public class SecureBufferedOutputStream extends BufferedOutputStream {
public SecureBufferedOutputStream(OutputStream out) {
super(out);
}
public SecureBufferedOutputStream(OutputStream out, int size) {
super(out, size);
}
@Override
public synchronized void flush() throws IOException {
super.flush();
Arrays.fill(buf, (byte) 0);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
Arrays.fill(buf, (byte) 0);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With