CVE-2014-8122 (Java, published 2015-02-13T15:59Z)
Description: value: Race condition in JBoss Weld before 2.2.8 and 3.x before 3.0.0 Alpha3 allows remote attackers to obtain information from a previous conversation via vectors related to a stale thread state.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-362 \u2014 Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
The product contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
Repository: https://github.com/weld/core
Files changed:
tests-arquillian/src/test/java/org/jboss/weld/tests/contexts/cache/ConversationScopedBean.java
tests-arquillian/src/test/java/org/jboss/weld/tests/contexts/cache/RequestScopedCacheLeakTest.java
tests-arquillian/src/test/java/org/jboss/weld/tests/contexts/cache/SimpleServlet.java
Commit message: WELD-1802 RequestScopedCache - Testcase


Vulnerable code:

Fixed code:
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.weld.tests.contexts.cache;

import java.io.Serializable;

import javax.enterprise.context.ConversationScoped;

@ConversationScoped
public class ConversationScopedBean implements Serializable {

    private String value = "foo";

    public String getAndSet(String newValue) {
        String old = value;
        value = newValue;
        return old;
    }
}
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.weld.tests.contexts.cache;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import junit.framework.Assert;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.weld.tests.category.Integration;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;

@RunWith(Arquillian.class)
@Category(Integration.class)
public class RequestScopedCacheLeakTest {

    @ArquillianResource
    private URL contextPath;

    @Deployment(testable = false)
    public static WebArchive getDeployment() {
        return ShrinkWrap.create(WebArchive.class).addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
                .addClasses(SimpleServlet.class, ConversationScopedBean.class);
    }

    @Test
    public void test() throws Exception {
        WebClient webClient = new WebClient();
        webClient.setThrowExceptionOnFailingStatusCode(false);
        for (int i = 0; i < 100; i++) {
            // first, send out a hundred of poisoning requests
            // each of these should leave a thread in a broken state
            sendRequest(webClient, i, true);
        }
        for (int i = 0; i < 100; i++) {
            // now send out normal requests to see if they are affected by the thread's broken state
            String result = sendRequest(webClient, i, false);
            Assert.assertFalse("Invalid state detected after " + (i + 1) + " requests", result.startsWith("bar"));
        }
    }

    private String sendRequest(WebClient webClient, int sequence, boolean poison) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
        final String path = getPath("getAndSet", sequence, poison);
        return webClient.getPage(path).getWebResponse().getContentAsString().trim();
    }

    private String getPath(String test, int sequence, boolean poison) {
        String path = contextPath + "/servlet?action=" + test + "&sequence=" + sequence;
        if (poison) {
            path += "&poison=true";
        }
        return path;
    }
}
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.weld.tests.contexts.cache;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jboss.weld.context.beanstore.ConversationNamingScheme;

@WebServlet(value = "/servlet", asyncSupported = true)
public class SimpleServlet extends HttpServlet {

    @Inject
    private ConversationScopedBean bean;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = req.getParameter("action");
        String sequence = req.getParameter("sequence");
        String poison = req.getParameter("poison");
        if ("getAndSet".equals(action)) {
            // the value should always be foo
            String value = bean.getAndSet("bar" + sequence);
            resp.getWriter().println(value);
            if (poison != null) {
                // this is a poisoning request
                // normal applications should never do something like this
                // we just do this to cause an exception to be thrown out of ConversationContext.deactivate
                req.removeAttribute(ConversationNamingScheme.PARAMETER_NAME);
            }
        } else {
            throw new IllegalArgumentException(action);
        }
    }
}