web-dev-qa-db-ja.com

memcpy()ベースの競合状態は、リモートコード実行を引き起こすために悪用可能ですか?

サンドボックスの信頼できる部分に次の疑似コードがあり、信頼できないコードがmprotect()mmap()ptrace()を直接呼び出せないようにしているとします(サンドボックス化されたメモリからマルチテキストにアクセスできません)

_//src and dest are user controlled but must be valid.
TrustedPart_for_safe_jit(void * mutext, uint8_t *src,uint8_t *dest, uint32_t size) // in the current case, *dest targets a PROT_NONE memory region
{
    MutexLock(mutext);
    ValidateOpcodesOrCrash(src,size); // uses calls to mmap on size internally. Contains many different loops and use several 10k thousands lines of codes in the trusted part of the sandbox : this is the longest part. Please also note that src is write protected while being in this function.
    unwriteprotect(dest,size); // calls many sandbox’s internal functions

    SafeMemcpy(src,dest,size); // THIS IS the function which contains the race condition

    asm("mfence");
    unEXECprotect(dest,size); // involve write protecting as well as allowing reading
    MutexUnlock(mutext);
}

SafeMemcpy(uint8_t *src,uint8_t *dest, uint32_t size) // the data to be copied cannot exceed 128Mb
{
    if(!CheckUserTargetPointToValidMemroyRange(dest,size) {
        uint8_t *src_ptr=src;
        uint8_t *dest_ptr=dest;
        uint8_t *end_ptr=des+size;
        while (dest_ptr < end_ptr) { // that loop should execute very fast
            *(uint32_t *) dest_ptr = *(uint32_t *) src_ptr;
            dest_ptr += 4;
            src_ptr += 4;
        }
    }
}
_

その部分は、信頼できないコードがtoコンパイルを使用できるようにする責任があります。
要点は、信頼されていないスレッドが中断されていないことです。

ご存知のように、2つのスレッドが同じ宛先でmemcpy()を使用すると、ランダムなデータが生成されます。その場合、そのようなデータには_int 0x80_のような命令が含まれる可能性があるため、サンドボックスをエスケープすることができます。

これまでに考えたこと:

  • データをファイルに書き込み、サンドボックスを介してreadシステムコールで読み取ります。メモリがまだ書き込み保護されている場合、プログラムはクラッシュしません。これにはループが含まれ、コピーされるデータが128Mbのサイズになる可能性がある場合でも、syscallのオーバーヘッドが原因で機能するかどうかはわかりません。
    別の方法は、コードを数回作成し、いくつかのタイミングで読み取りを試みることですが、初期タイミングウィンドウの選択方法に関するアイデア。
  • Futexを使用する…しかし、futexを使用して割り当てられていないメモリの値を確認できるかどうかはわかりませんでした。また、メモリが書き込み禁止になる前にスレッドが起動するかどうかもわかりません。

それで、memcpy競合状態のタイミングウィンドウを計画することは可能ですか?

10
user2284570

ここに表示される内容に基づいて、ValidateOpcodesOrCrashがメモリのその部分のチェックを終了した後、SafeMemcpyが開始する前に* srcを変更できます。

ValidateOpcodesOrCrashがどのように実装されているかはわかりませんが、[src,src+size]をループして不正な命令を探すだけだとすると、かなりのTrustedPart_for_safe_jitラージsizeを使用して呼び出すことができます。のCPUサイクルを確認し、ValidateOpcodesOrCrashがチェックを終了したと思われる*srcの上書きを開始します。 ValidateOpcodesOrCrashがより複雑な処理を行う場合、ValidateOpcodesOrCrashがチェックする最速かつ最速の命令シーケンスを特定し、最速の命令を最前部に配置し、最も遅い命令の多くを最後まで使用できます。 srcの上書きを開始する前に、ValidateOpcodesOrCrashが完了するのを待つ必要はおそらくないでしょう。

2
Lie Ryan

(免責事項:私はセキュリティの専門家ではありません。Cについてある程度の知識を持つ学生のみです)

これは、少なくともクラッシュを引き起こすために悪用される可能性が高いと思います。バグを修正するには、次のいずれかを行う必要があります。

  • destが書き込み可能である間、すべての信頼できないスレッドを一時停止します。
  • またはTrustedPart_for_safe_jit return 新しく割り当てられた実行可能メモリ(信頼できないコードがポインタとして任意のマシンのアドレスを不正に使用することは許可されていないと思います)。

つまり、ミューテックスを使用する代わりに、世界を止める必要があります。

0
Demi