---
# System prepended metadata

title: CVE-2021-39128

---

# CVE-2021-39128
## Context
Đợt mình này có gặp 1 case Jira version cũ đã patch các CVE critical có poc. Mặc dù cầm trong tay admin nhưng theo chính sách bảo mật của tổ chức chức năng **deploy plugin** đã bị vô hiệu hóa, nên tiến hành rà soát hệ thống và phân tích các CVE liên quan đến phiên bản đó nhằm phục vụ công tác đánh giá rủi ro và nghiên cứu chuyên sâu về Atlassian Jira.

Trong quá trình phân tích cho thấy **CVE-2021-39128** (Server-Side Template Injection). Mình đã nghiên cứu lỗ hổng này và thực hiện thành công việc **bypass sandbox** trong môi trường thử nghiệm phục vụ mục đích nghiên cứu.

## Mô tả
![image](https://hackmd.io/_uploads/rkipL9Nbbe.png)
Như mô tả thì CVE-2021-39128 là một lỗ hổng Server-Side Template Injection nằm trong tính năng Email Template của Atlassian Jira Server / Data Center cho phép kẻ có quyền JIRA Administrator chèn và thực thi mã Java tùy ý thông qua template email. Phiên bản bị ảnh hưởng: trước 8.13.12, và 8.14.0 → trước 8.19.1. Vendor đã phát hành bản vá cập nhật lên 8.13.12 hoặc 8.19.1 
## Phân tích
Như phần mô tả của CVE này cũng nói rõ là bug của tính năng email template, quyền cần thực hiện là Admin hoặc các user có quyền chỉnh sửa template.

Sau khi deploy được atlassian-jira-software-8.18.1 thì thử so sánh với version fix atlassian-jira-software-8.19.1 xem có gì khác biệt không

![image](https://hackmd.io/_uploads/SJElDqEW-e.png)
Khi nhìn thấy họ thay đổi nhiều thế này nên không thể nào đọc từng file rồi xem nó thay đổi gì được vì họ nâng cấp phần mềm cùng với việc fix lỗ hổng.

Không thể đọc hết được chỗ thay đổi này, nếu bắt buộc phải đọc thì mình đọc những file code java bị thay đổi thôi. 

Đọc phần so sánh không thấy gì thôi thì dựng môi trường, lưu ý nên bật mode **Contact Administrators Form ON**  (liên quan đến chức năng này đã từng có  từng đã có CVE-2019-11581 tại Subject nhưng chúng ta không khai thác ở đây**)** gửi email có thể có các chức năng khác gửi mail tùy vào các plugin trong hệ thống nhưng bật form này lên để thuận tiện cho việc gửi mail và debug hơn
![image](https://hackmd.io/_uploads/BksWP9E-Ze.png)
đọc mô tả thì phải tìm kiếm phần email templates
thì thấy được phần hướng dẫn trên document của họ, hướng dẫn lấy email templates

![image](https://hackmd.io/_uploads/HkXmP54W-l.png)
Bắt tay vào sửa luôn thử xem có chạy được không
![image](https://hackmd.io/_uploads/SJ-NP9EWZg.png)
Nhưng có vẻ như nó không parse rồi
![image](https://hackmd.io/_uploads/BJGHP5NZ-l.png)
Vậy giờ khi muốn khai thác lỗi SSTI thì ta phải biết nó parse những phần gì có trong template đặc biệt khi có sandbox, cách tốt nhất là debug và xem lúc email nó render
![image](https://hackmd.io/_uploads/r1DYwc4ZZl.png)
và đây là những gì khi email nó sử dụng các parameter khác nhau.

theo mình thấy có 28 templateParameter thôi vậy nên sẽ tìm hiểu hết chỗ đó có những class gì, nhưng đặc biệt thì hãy quan sát các templateParameters có tên đặc biệt hoặc liên quan đến jira

thì có `JiraUtils` 
`public static <T> T loadComponent(Class<T> componentClass)`
![image](https://hackmd.io/_uploads/H160vq4W-e.png)
và `I18n`
`public final Class<?> getClass()`
![image](https://hackmd.io/_uploads/SkI7u5Nbbl.png)
Sau đó vào sửa template xem có gì render ra không
![image](https://hackmd.io/_uploads/SkwHucNb-e.png)
và nó đã hoạt động , hiển thị ngày giờ.
![image](https://hackmd.io/_uploads/BkHI_5EWZg.png)
Theo như đó thì mình thấy `java.lang.Runtime` đã bị chặn rồi.

Giờ đến phần trace và suy nghĩ làm sao để có thể biết được phần sandbox chặn ở đâu.

Như phần trên đã mở phần `ContactAdministrators` rồi, giờ ta vào gửi mail cho thuận tiện thôi
![image](https://hackmd.io/_uploads/HkNudcV-Zx.png)
Khi gửi mail thì ta bắt được request ở burp đến `ContactAdministrators`
![image](https://hackmd.io/_uploads/S1gqOcNZ-e.png)
Chúng ta trace trong code![image](https://hackmd.io/_uploads/SJTcOcVZbx.png)
Luồng đi của code sẽ như thế này
![image](https://hackmd.io/_uploads/HJTo_9E-Zx.png)
![image](https://hackmd.io/_uploads/Sym2OcNZZg.png)
Mở thử file `velocity-email.properties` ra xem bên trong
Những class và packages bị chặn đều nằm trong này hết:
![image](https://hackmd.io/_uploads/HypTdcE-Ze.png)
Oke vậy chúng ta đã biết được nó chặn những gì rồi
Nó check ở đâu và check những gì thì ở trong hàm dưới hình

![image](https://hackmd.io/_uploads/B1S1F94W-g.png)
vậy giờ ta đem so sánh với bản vá xem có gì khác biệt.
![image](https://hackmd.io/_uploads/H11eK94--x.png)

Thì đây là kết quả

Từ dữ kiện này làm sao để có thể load được `Class webwork.util.ValueStack`

Khi tìm hiểu thì mình thấy trong phần object này có 2 function quan trọng là 

`pushValue()`
![image](https://hackmd.io/_uploads/rkWfFc4ZZe.png)
`findValue()`
![image](https://hackmd.io/_uploads/H14XY5VW-l.png)
Kết hợp 2 phần của jira và ValueStack đó lại ta sẽ load được webwork.util.ValueStack sử dụng được 2 function của nó
![image](https://hackmd.io/_uploads/r1bq9qEZZx.png)
![image](https://hackmd.io/_uploads/H1IK994-Wg.png)
Oke mình đã gỡ được khúc mắc là làm sao có thể gọi tới `webwork.util.ValueStack` nhưng mà giờ lại thêm một điều nữa là làm sao từ  `webwork.util.ValueStack`  có thể thực hiện lệnh từ xa bằng `static method`
thì mình biết cơ chế gọi của ValueStack sẽ xử lý OGNL
Giải thích về cách gọi của ValueStack thông qua pushValue và findValue
![image](https://hackmd.io/_uploads/S10T99VW-e.png)
Đầu tiên ta phải khởi tạo được một object như ví dụ trên hình là `java.lang.StringBuilder`

Sau đó mình gọi tới hàm `pushValue` rồi đưa `input object $sb` vừa được khai báo ở bên trên vào

Lúc đó `pushValue` sẽ đẩy `$sb` vào stack, lúc đó velocity sẽ không check blacklist bên trên nữa

Rồi gọi tới hàm `findValue` để gọi tới function có của object đó như ví dụ trên hình là `append()` và `toString()` thì kết quả nó trả về như sau
![image](https://hackmd.io/_uploads/HyuNjqEWZg.png)
Luồng của nó sẽ như thế này:
![image](https://hackmd.io/_uploads/Hydroq4Zbx.png)
Ok vậy ta hoàn thành payload thực hiện lệnh dựa trên các dữ kiện phân tích ở trên thôi.![image](https://hackmd.io/_uploads/HkiHTcEWWl.png)

![image](https://hackmd.io/_uploads/BJmincN-Wg.png)
Vậy chúng ta đã bypass được sandbox và chạy được lệnh từ xa.
Cảm ơn mọi người đã đọc tới đây cùng mình

## Reference

https://jira.atlassian.com/browse/JSDSERVER-8665

https://docs.atlassian.com/software/jira/docs/api/8.4.1/com/atlassian/jira/util/JiraUtils.html

https://community.atlassian.com/forums/Jira-questions/JIRA-Admin-Alert-i18n-getClass-forName-java-lang-Runtime/qaq-p/1132277

https://docs.atlassian.com/DAC/javadoc/opensymphony-webwork/1.4-atlassian-17/reference/webwork/util/ValueStack.html

https://www.naukri.com/code360/library/value-stack--ognl