作者:areuu
原文鏈接:https://mp.weixin.qq.com/s/UllCnLCF4XQIC5WxrZYJbQ

本文介紹一個簡便的方法構建自動挖掘chromium 框架。主要的想法是自動去跑生成的testcase ,然后檢測結果是否觸發了ASAN,觸發了的話自動郵件發送符號化的郵件。

單純的挖chromium,看你怎么挖了,有些漏洞window.close() 再加上一些features 開關,配合用戶操作就可以挖到一批,也有些poc 是直接是for 循環幾個 js api,在event handler中來個postmessage 來detach 某內存,或者是gc 或者刪除某個對象來釋放對象。這poc 看起來構造也容易,想著如何fuzz 的話應該比較大概率可以通過fuzz 挖到。

首先需要個asan 編譯的chromium 預編譯文件,一般的可以從 https://alesandroortiz.com/articles/latest-chromium-asan-builds/ 來下載

或者通過查找chromium base position 然后通過gsutil 來下載

這里祭出本人使用的腳本query.sh

#!/usr/bin/env bash

BASE='https://omahaproxy.appspot.com/deps.json?version='
GSUTIL_LINUX='gsutil ls "gs://chromium-browser-asan/linux-release/asan-linux-release-'


if [ $# != 1 ]; then
  BASE_VERSION=`curl $BASE 2> /dev/null | jq -r ".chromium_version"`
  BASE_POSITION=`curl $BASE 2> /dev/null | jq -r ".chromium_base_position"`
  V8_VERSION=`curl $BASE$BASE_VERSION 2> /dev/null | jq -r ".v8_version"`
  echo "current stable version: $BASE_VERSION"
  echo "v8 version: $V8_VERSION"

#  show
  exit 1
fi


VERSION="$1"
DOWNLOAD_URL=$BASE$VERSION
BASE_POSITION=`curl $DOWNLOAD_URL 2> /dev/null | jq -r ".chromium_base_position"`
V8_VERSION=`curl $DOWNLOAD_URL 2> /dev/null | jq -r ".v8_version"`
echo ""
echo "chromium base position: $BASE_POSITION"

echo "v8 version: $V8_VERSION"

if [ "$2" = "win" ];
then
  echo "yes";
fi

ex:

?  browser git:(master) query.sh 106.0.5249.119
chromium base position: 1036826
v8 version: 10.6.194.18
^C
?  browser git:(master) gsutil ls "gs://chromium-browser-asan/linux-release/asan-linux-release-103682*.zip"
gs://chromium-browser-asan/linux-release/asan-linux-release-1036821.zip
gs://chromium-browser-asan/linux-release/asan-linux-release-1036825.zip
gs://chromium-browser-asan/linux-release/asan-linux-release-1036826.zip

之后cp 來下載

?  browser git:(master) gsutil cp gs://chromium-browser-asan/win32-release_x64/asan-win32-release_x64-1036825.zip .

運行和檢測ASAN 信息

asan chromium 在觸發漏洞時會打印sanitize 信息來檢測,將輸出信息不斷的進行檢測sanitize 標頭即可。

可以選擇直接使用linux 腳本來跑,然后檢測下返回碼,最初也是這么跑的

...
export ASAN_OPTIONS=detect_leaks=0
export USE_ZEND_ALLOC=0

while true; do

  if [ $(ls $FUZZDIR/$NODE/ | wc -l) -eq 0 ]; then
    echo "Waiting for more tests..."
    sleep 2
    continue
  fi

  TEST=$(ls $FUZZDIR/$NODE/ | head -n1)

  echo -n "Testing $TEST: "

  OUTPUT=$(timeout -s SIGTERM $TIMEOUT $CHROMIUM/chrome --user-data-dir=$USERDIR --disable-gpu --headless --no-sandbox --js-flags='--expose_gc' --enable-blink-test-features --disable-popup-blocking --ignore-certificate-errors --enable-experimental-web-platform-features --enable-features=AutofillAddressProfileSavePrompt  $FUZZDIR/$NODE/$TEST 2>&1 | $MAIN_CHROMIUM/src/tools/valgrind/asan/asan_symbolize.py > $ASANLOG)
  RET=$?

  if [ $RET -ne 0 ]; then
  ...
    echo -e "\e[31;1mCRASH (ret:$RET)\e[0m"
    mv $FUZZDIR/$NODE/$TEST /mnt/fuzz/crashes/$TEST$(date)
    mv $ASANLOG /mnt/fuzz/crashes/$TEST$(date).asan.log
...

跑起來飛快,1秒可能跑1,2個吧

配合個某個generator,跑了一晚跑出了個asan,最后不出意外的還是出意外了:(

由于不滿足測試速度,去尋找其他方案。一般的跑testcase 可以放在iframe 里面不斷加載,像fuzz in sixty seconds 那樣,也可以使用extensions 來不斷開tab 來加載,或者在網頁中open 個testcase ,然后關閉。

在github 上搜了一下mozila 開發了ffpuppet 來fuzz 他們的firefox,有現成的我就直接拿來用,這里做了一些修改,來適應chromium,同時添加一些自定義參數。

web server

這里選擇使用了web server 來提供testcase ,通過訪問一個url 然后返回testcase url 來測試。

直接使用php + redis,從redis 來獲取有generator 生成的testcase。這樣可以可以實現分布式測試,提高fuzz 效率。

<!doctype html>
<html>

<head>
  <script>
    var file = null;
    var run_count = 0;
    var bFinish = false;



    onload = function fLoad() {

      var xhr = new XMLHttpRequest();
      xhr.onload = function (e) {

        console.log(file);
        file = JSON.parse(xhr.response).file;

        if (bFinish == false)
          bFinish = true;

        document.title = "Loading " + file;
        console.log(">>>>> " + file);


      }
      xhr.open('GET', '/next.php?action=query');
      xhr.send(null);

      var oFrame = open("/testcase/" + file + ".html");
      console.log("<<<<<<< " + file);

      setTimeout(fCleanup, 200);

      function fCleanup() {
        //  setTimeout(function() {
        try {
          if (bFinish == true) {
            bFinish = false;

            oFrame.close();
          }
        } catch (e) { };
        //      }, 200);
        fLoad();
      }
    }
</script>
</head>

<body>
</body>

</html>%

testcase 生成

你猜

看你想fuzz 哪個組件,然后看規范,收集api,寫規則。。。

自動化

開個cron job,自動從github pull寫好的generator,以及不斷檢測是否有crash 文件生成,有的話直接發郵件過去。

最終

不過還是審計吧


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2012/