Thread: md5 authentication bug?
Hello, I think I found a MD5 authentication bug in the PostgreSQL JDBC driver (PostgreSQL 7.2.1). In the openConnection() [Connection.java], the MD5 salt is converted to type String. And then, MD5Digest.encode() is called with this String. byte[] rst = new byte[4]; rst[0] = (byte)pg_stream.ReceiveChar(); rst[1] = (byte)pg_stream.ReceiveChar(); rst[2] = (byte)pg_stream.ReceiveChar(); rst[3] = (byte)pg_stream.ReceiveChar(); salt = new String(rst, 0, 4); ... byte[] digest = MD5Digest.encode(PG_USER, PG_PASSWORD, salt); But, it is not guaranteed that any byte[] is convertible to type String. So, it should change the MD5Digest.encode method's interface like below. public static byte[] encode(String user, String password, byte[] salt) It must not convert the MD5 salt to type String. I wrote an test program as below. It is difference between orig_byte and conv_byte. byte[] orig_byte = new byte[4]; orig_byte[0] = (byte) 0x36; orig_byte[1] = (byte) 0x91; orig_byte[2] = (byte) 0xce; orig_byte[3] = (byte) 0xb9; System.out.println(System.getProperty("file.encoding")); System.out.println("==="); for (int i = 0; i < orig_byte.length; i++) { System.out.println(orig_byte[i]); } System.out.println("==="); String salt = new String(orig_byte, 0, 4); byte[] conv_byte = salt.getBytes(); for (int i = 0; i < conv_byte.length; i++) { System.out.println(conv_byte[i]); } Results: On Linux(x86) / J2SE 1.4.1-beta ANSI_X3.4-1968 === 54 -111 -50 -71 === 54 63 63 63 On Solaris(SPARC) / J2SE 1.3.1_04 eucJP === 54 -111 -50 -71 === 54 63 Thank you, Jun Kawai
> I think I found a MD5 authentication bug in the PostgreSQL JDBC > driver (PostgreSQL 7.2.1). I forgot to attach a diff file. Thank you. Jun Kawai
Attachment
Patch applied by Dave Cramer. --------------------------------------------------------------------------- Jun KAWAI wrote: > Hello, > > I think I found a MD5 authentication bug in the PostgreSQL JDBC > driver (PostgreSQL 7.2.1). > > In the openConnection() [Connection.java], the MD5 salt is converted > to type String. And then, MD5Digest.encode() is called with this > String. > > byte[] rst = new byte[4]; > rst[0] = (byte)pg_stream.ReceiveChar(); > rst[1] = (byte)pg_stream.ReceiveChar(); > rst[2] = (byte)pg_stream.ReceiveChar(); > rst[3] = (byte)pg_stream.ReceiveChar(); > salt = new String(rst, 0, 4); > ... > byte[] digest = MD5Digest.encode(PG_USER, PG_PASSWORD, salt); > > But, it is not guaranteed that any byte[] is convertible to type String. > So, it should change the MD5Digest.encode method's interface like below. > > public static byte[] encode(String user, String password, byte[] salt) > > It must not convert the MD5 salt to type String. > > > I wrote an test program as below. > It is difference between orig_byte and conv_byte. > > byte[] orig_byte = new byte[4]; > orig_byte[0] = (byte) 0x36; > orig_byte[1] = (byte) 0x91; > orig_byte[2] = (byte) 0xce; > orig_byte[3] = (byte) 0xb9; > > System.out.println(System.getProperty("file.encoding")); > System.out.println("==="); > > for (int i = 0; i < orig_byte.length; i++) { > System.out.println(orig_byte[i]); > } > System.out.println("==="); > > String salt = new String(orig_byte, 0, 4); > byte[] conv_byte = salt.getBytes(); > > for (int i = 0; i < conv_byte.length; i++) { > System.out.println(conv_byte[i]); > } > > Results: > > On Linux(x86) / J2SE 1.4.1-beta > > ANSI_X3.4-1968 > === > 54 > -111 > -50 > -71 > === > 54 > 63 > 63 > 63 > > On Solaris(SPARC) / J2SE 1.3.1_04 > > eucJP > === > 54 > -111 > -50 > -71 > === > 54 > 63 > > > Thank you, > > Jun Kawai > > > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org) > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Patch has been applied, Thanks, Dave On Thu, 2002-08-15 at 14:09, Jun KAWAI wrote: > > I think I found a MD5 authentication bug in the PostgreSQL JDBC > > driver (PostgreSQL 7.2.1). > > I forgot to attach a diff file. > > > Thank you. > > Jun Kawai > ---- > > diff -uNr postgresql-7.2.1.orig/src/interfaces/jdbc/org/postgresql/Connection.java postgresql-7.2.1/src/interfaces/jdbc/org/postgresql/Connection.java > --- postgresql-7.2.1.orig/src/interfaces/jdbc/org/postgresql/Connection.java Tue Dec 11 13:44:23 2001 > +++ postgresql-7.2.1/src/interfaces/jdbc/org/postgresql/Connection.java Tue Aug 13 20:43:24 2002 > @@ -67,6 +67,7 @@ > > // New for 6.3, salt value for crypt authorisation > private String salt; > + private byte[] md5salt = new byte[4]; > > // These are used to cache oids, PGTypes and SQLTypes > private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType > @@ -194,12 +195,11 @@ > // Or get the md5 password salt if there is one > if (areq == AUTH_REQ_MD5) > { > - byte[] rst = new byte[4]; > - rst[0] = (byte)pg_stream.ReceiveChar(); > - rst[1] = (byte)pg_stream.ReceiveChar(); > - rst[2] = (byte)pg_stream.ReceiveChar(); > - rst[3] = (byte)pg_stream.ReceiveChar(); > - salt = new String(rst, 0, 4); > + md5salt[0] = (byte)pg_stream.ReceiveChar(); > + md5salt[1] = (byte)pg_stream.ReceiveChar(); > + md5salt[2] = (byte)pg_stream.ReceiveChar(); > + md5salt[3] = (byte)pg_stream.ReceiveChar(); > + salt = new String(md5salt, 0, 4); > DriverManager.println("MD5 salt=" + salt); > } > > @@ -236,7 +236,7 @@ > > case AUTH_REQ_MD5: > DriverManager.println("postgresql: MD5"); > - byte[] digest = MD5Digest.encode(PG_USER, PG_PASSWORD, salt); > + byte[] digest = MD5Digest.encode(PG_USER, PG_PASSWORD, md5salt); > pg_stream.SendInteger(5 + digest.length, 4); > pg_stream.Send(digest); > pg_stream.SendInteger(0, 1); > diff -uNr postgresql-7.2.1.orig/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java postgresql-7.2.1/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java > --- postgresql-7.2.1.orig/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java Mon Nov 26 08:26:59 2001 > +++ postgresql-7.2.1/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java Tue Aug 13 20:40:00 2002 > @@ -21,11 +21,11 @@ > * > * @param user The connecting user. > * @param password The connecting user's password. > - * @param salt A four-character string sent by the server. > + * @param salt A four-byte salt sent by the server. > * > * @return A 35-byte array, comprising the string "md5" and an MD5 digest. > */ > - public static byte[] encode(String user, String password, String salt) > + public static byte[] encode(String user, String password, byte[] salt) > { > MessageDigest md; > byte[] temp_digest, pass_digest; > @@ -41,7 +41,7 @@ > > bytesToHex(temp_digest, hex_digest, 0); > md.update(hex_digest, 0, 32); > - md.update(salt.getBytes()); > + md.update(salt); > pass_digest = md.digest(); > > bytesToHex(pass_digest, hex_digest, 3); > ---- > > > ---------------------------(end of broadcast)--------------------------- > TIP 3: if posting/reading through Usenet, please send an appropriate > subscribe-nomail command to majordomo@postgresql.org so that your > message can get through to the mailing list cleanly