
Análise técnica e exploit de prova de conceito para o CVE-2021-26084, uma vulnerabilidade de injeção OGNL no Atlassian Confluence Server. Inclui detalhamento da causa raiz, mapeamento de parâmetros vulneráveis e orientação de detecção.
Escopo de impacto
Versão < 6.13.23
6.14.0 ≤ Versão < 7.4.11
7.5.0 ≤ Versão < 7.11.6
7.12.0 ≤ Versão < 7.12.5
Causa, Método de exploração
O Confluence utiliza um framework para mapear URLs para classes Java, criando o que é chamado de “action”. As Action URLs terminam com “.action” e são definidas no arquivo xwork.xml em confluence-.jar e no arquivo atlassian-plugin.xml nos arquivos JAR dos plugins inclusos. Cada action contém pelo menos um atributo name, que define o nome da ação, um atributo class, que define a classe Java que implementa a ação, e pelo menos um elemento result que determina qual template Velocity será exibido após a ação ser chamada, com base no resultado da ação. Os valores comuns retornados pelas ações são “error”, “input”, “success”, mas qualquer resultado pode ser usado se corresponder a um elemento result no XWork XML. As ações podem conter um atributo method que permite chamar um método específico da classe Java especificada. Quando nenhum método é especificado, o método doDefault() é chamado. Abaixo está o item de ação para a ação createpage-entervariables:

O método doEnter() da classe com.atlassian.confluence.pages.actions.PageVariablesAction processa as requisições para doenterpagevariables.action e retorna os valores “error”, “input”, “success”. Isso leva à renderização do template Velocity.
Aqui, o valor do atributo “name” de um elemento action corresponde a um caminho /.action e o elemento contém qual template será exibido como parte da resposta com base em error/success,... Portanto, neste exemplo, basta acessar /pages/doenterpagevariables.action para exibir o arquivo velocity template.

Podemos ver como o template Velocity é renderizado na página HTML

Inserindo o nome da tag no template como parâmetro e notando que os valores são obtidos do parâmetro da requisição e retornados na resposta.

Uso de #tag : #tag (“attribute1”, “attribute2”, “attribute3”)
Esses atributos durante a renderização são obtidos em AbstrctTagDirective.applyAttributes()

#tag ("Hidden" "name='queryString'" "value='ahihihi'")
Após os atributos serem extraídos pelo método AbstrctTagDirective.applyAttributes(), eles são passados para AbstrctUITag.doEndTag() → AbstractUITag.evaluateParams()

Em seguida, são passados para WebWorkTagSupport.findValue() → OgnlValueFinder.findValue() na forma de expression

Depois, passados para SafeExpressionUtil.isSafeExpression()

Aqui a expression foi compilada, verificada contra uma blacklist e colocada em cache. Através da etapa de compilação, ela é compilada para a forma ASTConst, que quando avaliada retorna a string previamente compilada.

Quando a expression recebe o caractere “'” da entrada, ele é escapado para uma entidade HTML

O ponto de escape está em HtmlAnnotationEscaper.annotatedValueInsert()

Aqui o método ognl.JavaCharStream.readChar() é chamado e avalia caracteres de escape Unicode, portanto, ao enviar “\u0027”, ele é convertido para “'”. Assim, é possível escapar e concatenar uma expression OGNL

Mas é necessário contornar a blacklist do OGNL da seguinte forma

É possível contornar usando Array accessors em vez do método “getClass” ou do atributo “.class”.
queryString=aaa\u0027%2b#{\u0022\u0022[\u0022class\u0022]}%2b\u0027bbb

Método de detecção
Monitorar todas as requisições HTTP cujo componente de caminho da URI contenha uma das strings na coluna "URI Path" da tabela a seguir:
URI Path | Vulnerable Parameters
/users/darkfeatures.action | featureKey
/users/enabledarkfeature.action | featureKey
/users/disabledarkfeature.action | featureKey
/login.action | token
/dologin.action | token
/signup.action | token
/dosignup.action | token
/pages/createpage-entervariables.action | queryString, linkCreation
/pages/doenterpagevariables.action | queryString
/pages/createpage.action | queryString
/pages/createpage-choosetemplate.action | queryString
/pages/docreatepagefromtemplate.action | queryString
/pages/docreatepage.action | queryString
/pages/createblogpost.action | queryString
/pages/docreateblogpost.action | queryString
/pages/copypage.action | queryString
/pages/docopypage.action | queryString
/plugins/editor-loader/editor.action | syncRev
Se for encontrada tal requisição, deve-se verificar o método HTTP da requisição. Se o método for POST, procurar os Vulnerable Parameters correspondentes da tabela acima no corpo da requisição HTTP; se o método for GET, procurar os parâmetros na URI da requisição HTTP. Verificar se o valor de algum Vulnerable Parameter contém a string “\u0027” ou sua forma codificada em URL. Se sim, o tráfego será considerado malicioso e um ataque explorando essa vulnerabilidade pode estar em andamento.