Thread: md5 authentication bug?

md5 authentication bug?

From
Jun KAWAI
Date:
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



Re: md5 authentication bug?

From
Jun KAWAI
Date:
> 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

Re: md5 authentication bug?

From
Bruce Momjian
Date:
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

Re: md5 authentication bug?

From
Dave Cramer
Date:
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