abonnement Unibet Coolblue
pi_184542981
Hey,

Even korte probleemintroductie, ik volg een vak cryptologie in mijn master industriële wiskunde, en voor dat vak heb ik een coding assignment om een soort 'capture the flag' spelletje te spelen, implementeer een oude hack op een kwetsbare server. De hack hier betreft om een zogeheten 'Oracle Attack' te doen, dat betekent zoiets als 'talloze berichten sturen' en aan de hand van die berichten voldoende informatie achterhalen om ciphercodes te ontsleutelen of berichten te vervalsen.

In dat geval betreft dat een achterhaalde hack gepubliceerd in 1998, meer daarover is te vinden op: http://archiv.infsec.ethz(...)bleichenbacher98.pdf

Deze link bevat een heldere (wiskundige) structuur alsmede een gedetailleerde beschrijving van de aanval. Mijn vraag gaat over het implementeren van zo'n kwetsbaar TLS protocol.

Ik draai een Ubuntu VM (16.04 volgens mij) met apache2 en openssl. Het kwetsbare TLS protocol maakt gebruik van een RSA techniek voor het overeenkomen van de sessie sleutel, ik heb de volgende ciphersuite TLS_RSA_WITH_AES_128_CBC_SHA op default gezet.

Nu moet ik dus een bericht genereren (geen probleem), van padding voorzien en naar de server sturen en de server geeft mij dan een response of die padding wel of niet correct is. Ergens staat dus in de source code die dat deel afhandelt, en in de bug fixes is dit orakel dus 'gefixt' maw die afhandeling geeft dus geen informatie meer vrij over een foute padding, én dat moet ik even rechtzetten.

Nu zei mijn TA het volgende: 'See the end of tls_process_cke_rsa() in
ssl/statem/statem_srvr.c of the current OpenSSL code, in particular lines
3101 through 3118.' maar dat kan ik dus niet vinden.

Iemand tips? :) cke staat voor 'client key exchange'
Fervent tegenstander van het korps lasergamers.
pi_184543535
Wat kun je niet vinden, het bestand of die functie? Voor het bestand moet je de broncode hebben, dat zit in een aparte src package, en die broncode moet je dan aanpassen en compileren lijkt me.
pi_184543731
quote:
0s.gif Op maandag 21 januari 2019 23:16 schreef Farenji het volgende:
Wat kun je niet vinden, het bestand of die functie? Voor het bestand moet je de broncode hebben, dat zit in een aparte src package, en die broncode moet je dan aanpassen en compileren lijkt me.
Inderdaad de source waar ik die methode kan wijzigen.
Fervent tegenstander van het korps lasergamers.
pi_184545792
quote:
0s.gif Op maandag 21 januari 2019 23:26 schreef Amoeba het volgende:

[..]

Inderdaad de source waar ik die methode kan wijzigen.
Source code kun je hier gewoon vinden. https://www.openssl.org/source/

Of even op github kijken (let op de versies/revisies)

https://github.com/openss(...)statem/statem_srvr.c
pi_184549649
quote:
12s.gif Op dinsdag 22 januari 2019 04:28 schreef devzero het volgende:

[..]

Source code kun je hier gewoon vinden. https://www.openssl.org/source/

Of even op github kijken (let op de versies/revisies)

https://github.com/openss(...)statem/statem_srvr.c
Ah ja, gevonden. Nu ben ik vaardig in matlab en java. Als het moet gaan R en mathematica ook nog wel, C++ en Flash zijn lang geleden ... maar C heb ik nog nooit eerder gedaan. :')

Anyway, even terug naar het probleem:
Regels [3000,3070] ongeveer van https://github.com/openss(...)statem/statem_srvr.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
     * We want to be sure that the plaintext buffer size makes it safe to
     * iterate over the entire size of a premaster secret
     * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
     * their ciphertext cannot accommodate a premaster secret anyway.
     */
    if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                 RSA_R_KEY_SIZE_TOO_SMALL);
        return 0;
    }

    rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
    if (rsa_decrypt == NULL) {
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                 ERR_R_MALLOC_FAILURE);
        return 0;
    }

Hier, neem ik aan, gebeurt de decryption van het bericht dat ik stuur?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    /*
     * We must not leak whether a decryption failure occurs because of
     * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
     * section 7.4.7.1). The code follows that advice of the TLS RFC and
     * generates a random premaster secret for the case that the decrypt
     * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
     */

    if (RAND_priv_bytes(rand_premaster_secret,
                      sizeof(rand_premaster_secret)) <= 0) {
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                 ERR_R_INTERNAL_ERROR);
        goto err;
    }

Ik heb geen idee wat dit doet..?

1
2
3
4
5
6
7
8
9
10
11
12
13
    /*
     * Decrypt with no padding. PKCS#1 padding will be removed as part of
     * the timing-sensitive code below.
     */
     /* TODO(size_t): Convert this function */
    decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
                                           PACKET_data(&enc_premaster),
                                           rsa_decrypt, rsa, RSA_NO_PADDING);
    if (decrypt_len < 0) {
        SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                 ERR_R_INTERNAL_ERROR);
        goto err;
    }
Beetje vaag dit maar het heeft toch geen zin om de padding te verwijderen en dan vervolgens te decrypten? Het idee is juist dat ná decryption een message (key exchange) een wel of niet correcte padding heeft. Mis ik iets?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    /* Check the padding. See RFC 3447, section 7.2.2. */

    /*
     * The smallest padded premaster is 11 bytes of overhead. Small keys
     * are publicly invalid, so this may return immediately. This ensures
     * PS is at least 8 bytes.
     */
    if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
        SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                 SSL_R_DECRYPTION_FAILED);
        goto err;
    }

    padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
    decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
        constant_time_eq_int_8(rsa_decrypt[1], 2);
    for (j = 2; j < padding_len - 1; j++) {
        decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
    }
    decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);


Ik denk dat het hier moet zijn. Zoals gezegd bestaat een padding uit [00,02,PS,00]|[D] en die padding is minimaal 11 bytes dus de padding string is minimaal 8 bytes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    /*
     * If the version in the decrypted pre-master secret is correct then
     * version_good will be 0xff, otherwise it'll be zero. The
     * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
     * (http://eprint.iacr.org/2003/052/) exploits the version number
     * check as a "bad version oracle". Thus version checks are done in
     * constant time and are treated like any other decryption error.
     */
    version_good =
        constant_time_eq_8(rsa_decrypt[padding_len],
                           (unsigned)(s->client_version >> 8));
    version_good &=
        constant_time_eq_8(rsa_decrypt[padding_len + 1],
                           (unsigned)(s->client_version & 0xff));

En dit lijkt weer een bugfix voor een gerelateerde aanval, maar dat lijkt me nu niet relevant.

Ziet iemand een vlugge manier om een andere error te genereren als de padding niet correct is?
Fervent tegenstander van het korps lasergamers.
abonnement Unibet Coolblue
Forum Opties
Forumhop:
Hop naar:
(afkorting, bv 'KLB')