Git Product home page Git Product logo

cve-2021-39115's Introduction

CVE-2021-39115

Template Injection in Email Templates leads to code execution on Jira Service Management Server

I) Bulding

Mình đã hướng dẫn deploy + debug ở đây, các bạn có thể tham khảo.

II) Phân tích

Trong Description của CVE này cũng đã nói rõ là bug nằm ở tính năng Email Template. Với quyền admin, user có thể tùy ý chỉnh sửa tempate của các email thông báo. Bug này cần quyền admin để thực hiện nên dù có RCE cũng không mấy nghiêm trọng, nhưng mình vẫn quyết định viết blog với mục đích cho vui :) bạn nào đang tìm hiểu SSTI có thể tham khảo.

  • Bắt đâu vào công chuyện, mình deploy bản atlassian-jira-servicedesk-4.17.0-m0006-standalone và thử diff xem nó với bản 4.18.0 có gì khác nhàu: image

Khi nhìn thấy đống này thì,.... tất nhiên là mình không đọc từ file một rồi, mình lười lắm. Đùa vậy chứ thực ra ngoài có thêm bản fix về security, các phiên bản còn có sự nâng cấp + thay đổi ở các tính năng. Mình diff tất cả rồi ngồi đọc như vậy rất tốn thời gian. Đương nhiên trong 1 số trường hợp mình phải chịu diff hết rồi ngồi đọc, nhưng với trường hợp này thì mình không làm thế =)))

  • Như đã nói ở trên, admin có quyền đổi template của tất cả các email trong báo. Vì thế, bước đầu tiên là mình cần biết trong quá trình parse các email thông báo thì sẽ có những context gì? điều này là đặc biệt quan trọng trong khi muốn khai thác bug SSTI (có sử dụng sandbox). Cách hiểu quả nhất chính là debug nhảy vào đoạn parse email template để xem value của biến context.
  • Tất nhiên là sẽ có nhiều loại thông báo khác nhau (SignUp, change Password,...), mỗi loại sẽ sửa dụng một endpoint khác nhau. Mình sử dụng tính năng SendBulkMail để tạo email thông báo. Về stack call của endpoint này như thế nào thì mình xin phép không đề cập tới tránh dài dòng vì nó tương tự như stack call trong CVE-2019-11581

Tại hàm SimpleNote.render mình có thể xem biến context để xem mình có thể tận dụng những gì:

Theo kinh nghiệm của riêng của mình, thì mình sẽ chú ý kiểm tra các context/class có những từ khóa như: Utils, Manager, service,... . Mình lưu ý thấy có context $jirautils (class com.atlassian.jira.util.JiraUtils) có chứa method public static <T> T loadComponent(String className, Class<?> callingClass) :

Mình lân la kiếm docs đọc xem chức năng của nó, nó xài như thế nào vì input đưa vào có String className cộng với output là một class nên rất có thể method này load class một cách tùy ý được:

  • Như docs có nói, hàm này để load các class :) Mình bắt đầu vào việc ngay xem method đó có thực sự load được class tùy ý hay không:

Mình bay vào System -> Email templates và tải file template hiện tại về máy

Có rất nhiều template khác nhau, mỗi cái xài riêng cho một loại thông báo khác nhau nên mình kiếm cái file nào mà nó có thể xài chung cho nhiều loại thông báo khác nhau như email\html\includes\header.vm

Sau khi up file template đã chỉnh sửa lên, và sử dụng SendBulkMail để gửi một email thông báo đi. Mình nhận được output trong email như thế này:

Đại loại là class này không có constructors hoặc không được chấp nhận. Mình thử sử dụng một class khác có constructors (constructors không input) thử xem sao:

Và kết quả đúng như mong đợi. mình đã lấy được class thành công:

  • Như vậy là ta đã có thể load class gần tùy ý rồi, cũng khá ổn. Nhưng làm sao để có thể RCE ??? jira sử dụng velocity template và có sandbox khá đầy đủ, với blacklist packages và blacklist class (với blacklist class nó có thể chặn tất cả các class được extends từ những class trong blacklist). Việc sử dụng các class được public ở trên mạng là điều gầnh như không thể. Tới đây mình bắt buộc phải diff giữa bản lỗi và bản fix xem chúng khác nhau như thế nào, tất nhiên mình sẽ không diff toàn bộ mà sẽ chỉ diff ở file conf của velocity (\atlassian-jira\WEB-INF\classes\velocity.properties) để xem có gì mới update hay không:

Ta thấy có 3 class được thêm vào blacklist :

org.springframework.expression.spel.standard.SpelExpressionParser,\
com.atlassian.jira.component.ComponentAccessor,\
com.atlassian.jira.plugin.ComponentClassManager

Khi kiểm tra từng class, mình nhận thấy tại class SpelExpressionParser có hàm public SpelExpression parseRaw(String expressionString), tra google một lát để tìm cách sử dụng thì đại loại nó có thể dùng như thế này:

#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')")

Như các bạn thấy, hàm parseRaw trả về một object là một class org.springframework.expression.spel.standard.SpelExpression chứ chưa thực sự render biểu thức mình đưa vào. Mình nhảy vào class SpelExpression và thấy có method getValue:

@Nullable
    public Object getValue() throws EvaluationException {
        CompiledExpression compiledAst = this.compiledAst;
        if (compiledAst != null) {
            try {
                EvaluationContext context = this.getEvaluationContext();
                return compiledAst.getValue(context.getRootObject().getValue(), context);
            } catch (Throwable var4) {
                if (this.configuration.getCompilerMode() != SpelCompilerMode.MIXED) {
                    throw new SpelEvaluationException(var4, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION, new Object[0]);
                }
            }

            this.compiledAst = null;
            this.interpretedCount.set(0);
        }

        ExpressionState expressionState = new ExpressionState(this.getEvaluationContext(), this.configuration);
        Object result = this.ast.getValue(expressionState);
        this.checkCompile(expressionState);
        return result;
    }

Nhìn vào input/output, một người chơi hệ tâm linh như mình quyết định thử luôn chứ không coi docs nữa:

#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')").getValue()

và kết quả:

III) Kết Luận

Như thế ta đã có thể bypass sanbox của velocity để RCE, thế nhưng khi đặt mình vào trường hợp của author - người tìm ra bug này thì còn có nhiều câu hỏi mà mình không thể giải thích được:

  • Vì sao có tới 3 class được thêm vào black list?

khi mình tìm hiểu 3 class này, mình thấy chúng có thể tạo thành mội chain:

ComponentAccessor.getComponentClassManager() 
  => ComponentClassManager.newInstance(String className) (Class này có thể load class tùy ý)
        => SpelExpressionParser

nếu như author sử dụng $jirautils giống mình thì sẽ không cần tới 2 class kia làm gì. Nhưng nếu author không sử dụng $jirautils thì làm sao để có được ComponentAccessor???

  • Làm sao author có thể tìm ra được 3 class trên? Đây là câu hỏi mình lưu tâm và muốn được biết nhất, nhưng có lẽ chỉ có cách liên hệ trực tiếp với author thì mình mới biết được. Tiếc là mình không biết author của bug này là ai.

IV) Tiếp tục bypass bản patch

cve-2021-39115's People

Contributors

petrusviet avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.