ในการวิเคราะห์ติดตามผลการโจมตี SolarWinds เราจะให้รายละเอียดว่าข้อมูลถูกส่งไปยังผู้โจมตีอย่างไร
หากมีการส่งข้อมูลไปยังผู้โจมตีอันเป็นผลมาจากคำสั่ง แทนที่จะดำเนินการตามคำขอ HTTP(S) GET ซึ่งเป็นสิ่งที่เราอธิบายไว้ในบล็อกที่แล้ว Sunburst จะเริ่มต้นคำขอ HTTP(S) POST
Sunburst ใช้เส้นทาง URL ที่สร้างแบบสุ่มสำหรับคำขอ HTTP(S) POST ที่แตกต่างจากคำขอ HTTP(S) GET
หากข้อมูลที่ส่งมากกว่า 10,000 ไบต์ เส้นทาง URL จะเป็นดังนี้:
- /pki/crl/{0}{1}-{2}.crl
- element 0 is a number between 100 and 10,000
- element 1 is optionally one of the following:
- -root
- -cert
- -universal_ca
- -ca
- -primary_ca
- -timestamp
- -global
- -secureca
- element 2 is the last error code
ส่วนหัว Content-Type ถูกตั้งค่าเป็น application/octet-stream และข้อมูล POST จะตามมา ข้อมูล POST ประกอบด้วยข้อมูลที่ส่งแบบเข้ารหัส UTF8 เชื่อมกับรหัสข้อผิดพลาดล่าสุด ต่อด้วยรหัสผู้ใช้ และบีบอัดในภายหลัง ทุกๆ ไบต์ของ Blob ที่บีบอัดจะถูกรวมเข้าด้วยกัน และใช้ไบต์ต่ำสุดของค่าผลรวมเป็นคีย์ Blob ที่บีบอัดคือ XOR โดยไบต์ของคีย์และไบต์ของคีย์จะถูกเพิ่มไว้ข้างหน้าข้อมูลที่เข้ารหัส
รูปที่ 1. โครงสร้างของข้อมูล Sunburst POST
หากข้อมูลที่ส่งน้อยกว่าหรือเท่ากับ 10,000 ไบต์ เส้นทาง URL จะใช้รูปแบบใดรูปแบบหนึ่งจากสองรูปแบบดังนี้:
- /fonts/woff/{0}-{1}-{2}-webfont{3}.woff2
- element 0 is a random number between 100 and 10,000
- element 1 is “opensans” or “noto”
- element 2 is one of the following:
- bold
- bolditalic
- extrabold
- extrabolditalic
- italic
- light
- lightitalic
- regular
- semibold
- semibolditalic
- element 3 is the last error code
- or /fonts/woff/{0}-{1}-{2}{3}.woff2
- element 0 is a random number between 100 and 10,000
- element 1 is one of the following:
- freefont
- SourceCodePro
- SourceSerifPro
- SourceHanSans
- SourceHanSerif
- element 2 is one of the following:
- Bold
- BoldItalic
- ExtraBold
- ExtraBoldItalic
- Italic
- Light
- LightItalic
- Regular
- SemiBold
- SemiBoldItalic
- element 3 is the last error code
นอกจากนี้ แทนที่จะส่งข้อมูลที่เข้ารหัสโดยตรง เนื่องจากเมื่อข้อมูลมีขนาดใหญ่กว่า 10,000 ไบต์ ข้อมูลจะถูกส่งแบบ steganographically ในรูปแบบ faux JSON blob
JSON blob มีฟิลด์ต่อไปนี้:
- userId – มี ID ผู้ใช้ที่สับสนใน GUID
- sessionId – GUID ที่สร้างขึ้นแบบสุ่มต่อเซสชัน HTTP
- Timestamp – มิลลิวินาทีตั้งแต่ปี 1970/1/1 ลบห้านาที บวกกับค่าสุ่มระหว่าง 0-512 โดยปกติบิตที่สองตั้งค่าเป็น 1
- Index – ค่าที่เพิ่มขึ้น
- EventType – ตั้งค่าเป็น Orion
- EventName – ตั้งค่าเป็น EventManager
- DurationMs – ค่าสุ่มเดียวกันระหว่าง 0-512 ที่ใช้ใน Timestamp
- Succeeded – ตั้งค่าเป็นจริง
- Message – ส่วนของข้อมูลที่เข้ารหัส Base64
ข้อมูลที่เข้ารหัสเพื่อส่งแบ่งออกเป็นกลุ่มขนาดหลายตัวแปร ขนาดของแต่ละส่วนจะถูกกำหนดแบบสุ่ม แต่โดยทั่วไปจะเปลี่ยนจากเล็กไปใหญ่ หากขนาดที่เลือกแบบสุ่มเป็น 0 อันที่สุ่มระหว่าง 16 ถึง 28 ไบต์จะถูกสร้างขึ้นแทน และค่าการประทับเวลาคือ AND มีค่า 18446744073709551613 ซึ่งสำคัญกว่าคือตั้งค่าบิตที่สองเป็น 0 จากนั้นแต่ละอันจะถูกเข้ารหัสและเพิ่มลงใน JSON blob และส่งเป็นข้อมูล HTTP(S) POST โดยตั้งค่าส่วนหัวประเภทเนื้อหาเป็น application/json
รูปที่ 2 ตัวอย่างที่ประดิษฐ์ขึ้นของไฟล์ JSON ที่จะส่งโดย Sunburst
เมื่อได้รับแล้ว ผู้โจมตีจะต้องถอดรหัสและเชื่อมส่วนข้อความทั้งหมดเข้าด้วยกัน โดยข้ามกลุ่มขยะที่ไม่ได้ตั้งค่าบิตการประทับเวลาที่สอง