0

i'm trying to fix a critical bug emerged during a penetration test on our application.
Environment: an old Gupta/SQL Windows desktop application that need the support from a java webapp (hosted on IBM WebSphere) to operate on db/communicate on CICS; during the penetration test we were able to act a Man in The Middle and sniff/send command to the java webapp, getting full access to the db.

As a fix i've thought about implementing Mutual authentication between client and server; unlucky we cannot use TLS / 2-way-ssl since Gupta doesn't support it. (as the Gupta developer say, i'm the java one). So we're trying to implement a simpler MA, adding an encrypted password on every transaction between client and server (made "random" encrypting a static text + timestamp), to be decrypted and verified on every exchange.

Here the problem: on our actual test the two application encrypt the same string in different outputs
This is my aes256 encrypter, with password generated from a String + fixed salt

private static final String SECRET_KEY = "PasswordTest123";
private static final String SALT = "sssshhh!";

public static void main(String[] args) {

    TestTest asd = new TestTest();
    System.out.println(asd.encrypt("TestStringTestString10:45:12"));

}

public static String encrypt(String strToEncrypt) {
    try {
        byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        IvParameterSpec ivspec = new IvParameterSpec(iv);

        // we're on java 7 and "PBKDF2WithHmacSHA256" seems not available, got exception
        // SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(SECRET_KEY.toCharArray(), SALT.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);

        byte[] message = cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8));
        String s = new String(message);
        System.out.println(s);
        String encoded = DatatypeConverter.printBase64Binary(message);
        return encoded;

    } catch (Exception e) {
        System.out.println("Error while encrypting: " + e.toString());
    }
    return null;
}

Output:
R_.m]wcý7uÒ¨Im„çYSç.?®ôZ†»Y
Ul8uf21dd2P9Azd10qgOSW2E51lT5y4/rvQIWoa7WRY=

Here the Gupta/SQL Windows app encrypt, with the same password/parameters:
lDEd+PLT5wmPTyZhqvGMgbKc9djCrJLjsZeGlYnjO8A=

Notes: on the desktop app we're using the CryptEncrypt class to perform encryption, but seems to not be a Salt from password option.

i'm no AES256 expert, which is the parameter that is giving us a different result? the salt? the iv? also i'd appreciate some links to doc, everything i found are "commercial" articles about AES, i need something to understand salt-iv

Thanks a lot!


EDIT: If we use a different Salt/IV on both sides, we will be able to encrypt/decrypt the string?

Pari
  • 1
  • 6
  • Salt is something extra you add to the data to be encrypted; it should be random data and discarded when decrypted (looks like you are using _timestamp_ - not a good salt - for this). IV populates the initial state of the encryption/decryption algorithm and needs to the same value when decrypting; it can be sent (in the clear) with the encrypted message with no security implications. Salt and IV should be different for every message and therefore encrypting the same plain-text will produce a different encrypted message body. – Richard Critten Jun 03 '21 at 09:57
  • I'm using the timestamp in the string to be encrypted, since i need the encrypted string to be different on every transaction; in fact if i run the encrypt again with the same input/passwrod/salt i get the same output every time. Is that right? if i remove the timestamp and use different salt/iv every time the other side will be able to decrypt anyway? – Pari Jun 03 '21 at 10:13
  • Both of your String to binary conversions (SECRET_KEY.toCharArray(), SALT.getBytes()) doesn't use a charset - try to use UTF-8 as well as you do for "strToEncrypt". – Michael Fehr Jun 03 '21 at 14:44
  • 2
    I know about the Gupta part: Since Gupta uses the Win-API-function CryptEncrypt() there might be an issue with string encoding. It's easy to accidently pass the string to encrypt in UTF-16 format. Another issue can be that the terminating 0 is handled differently in your Java application vs. the Win-API part. – Thomas Uttendorfer Jun 04 '21 at 15:36
  • Thanks a lot for the comments, i will try checking the encoding on both sides; two problem: (Java)how can i specify the encoding in the "SECRET_KEY.toCharArray()" function? @ThomasUttendorfer Can u give some info about how to check the encoding on Gupta? could some code help? – Pari Jun 08 '21 at 14:51
  • 1
    On Gupta there are the following aspects: Is Gupta-Version < 5.0? Then the internal encoding is ANSI(!). If the version is above the internal encoding is the same as in Windows UTF-16 LE. Another aspect is how the windows-dll-functions are declared in Gupta (there are a lot possiblities: LPSTR, LPWSTR, LPVOID). Then there is an explicit conversion function SalStrToMultiByte() where you can convert an internal String to a BinaryBuffer with the desired encoding. And last but not least - maybe the terminating 0 are part of the encryption what you usually don't want. Good luck. – Thomas Uttendorfer Jun 09 '21 at 15:34

0 Answers0