git‑shell (/bin/bash
は実行するプログラムに置き換えられているため、他のことを行うことはできません):
struct _raw_uncapped_ssh_string { // no limit on the size of the string; uint32_t len; char non_null_terminated_string[]; // by protocol design it have a minimum length of 1 }; typedef struct _raw_uncapped_ssh_string raw_ssh_string; union buffer { void * uncapped_zlib_decompressed_network_data; // yes, the size is uncapped, so it’s possible to put 4Gb of // data in it that would be copied later into memory. zlib // allow easily to turn some Mb in Gb of data, but it’s not // the point of the question. raw_ssh_string st; }; get_command (compressed_network_data) { size_t len; char * command; buffer string=uncompress_to_buffer(compressed_network_data); len=ntohl(string.st.len)+1; command=malloc(len+1); command[len]=0; // here’s the point, both the string length and content as // well it’s supplied size is controlled by the attacker. memcpy(command,string.st.data,len); return command; }
これがコマンドが後でどのように実行されるか(文字列command
はget_command()
の後も変更されません)。
const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell. // redirect the program output to the network. dup2(stdin, 0); dup2(stdout,1); dup2(stdout,2); close(stdin); close(stdout); //if this return execution failed and print an error message return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour.
memcpy(command,string.st.data,0)
memcpy
の3番目のメンバーが最小サイズは1で、私のコンテキストでは、size_t
は64ビットの整数を使用していますが、len
。
私にできることは、len
をstring.st.data
に割り当てられた値よりも大きい値に設定することだけです。これは、未割り当てのメモリを読み取ることができるバッファアンダーフローです。
サーバーメモリを読み取ることはできますが、パブリックsshサーバーが保持できる機密データを確認できません(私の場合は、 ssh is publicを実行できます)。
リモートでのバッファアンダーフローも同様ですmemcpy
コード実行?
コメント
回答
一般に、いいえ、バッファアンダーフローをリモートコード実行に使用することはできません。攻撃者が制御するデータが割り当てられたスペースを離れることはないため、プログラムの実行フローを引き継ぐことはできません。
バッファアンダーフローには、次のような他のタイプの攻撃の可能性があります。情報の開示(プログラムがバッファの元のコンテンツが新しいデータによって消去されることを期待している場合)
コメント
- または私として最近gitで見たが、後でバッファオーバーフローに変わる。
回答
この応答を最初に書いたとき、あなたが抱いているいくつかの誤解を私は理解したようです。これらの誤解は、あなたが私の答えを理解するのを妨げる可能性があります。明確にするために、私はこのテキストを大きくして強調し、軽蔑しないようにします。
使用する用語の多くは、あなたがそれらが意味すると思われることを意味するものではありません。
例:
- “
memcpy
” の3番目のメンバーは、は関数であり、
struct
またはunion
ではありません。 - 「
len
“があるため、バッファオーバーフローを実行できません。また、ガソリンがあるため、ガソリンが不足することはありません。質問?特に理論的に言えば、あなたのコードはバッファオーバーフローを引き起こす可能性があるので、私にはぴったりのアナロジーのようです。 - 「私にできることはを設定することだけです。 div id = “82b7b4b452″>
をstring.st.data
に割り当てられた値よりも大きい値にします。これはバッファアンダーフローです…」いいえ、これはバッファアンダーフローの定義ではありません。負のインデックスまたは原因となるインデックスを使用して範囲外の配列にアクセスすると、バッファアンダーフローが発生します。ポインタ演算のラッピングが発生します。後者は一部の構成で可能かもしれませんが(「64ビットシステム」でも、それが意味するものは何でも)、これらの単語を書いていたときにこれが意味したことではないかと思います。 with:
calloc
またはmemset
)。 char *fubar = NULL;
について少し考えてみましょう…この種のポインタは通常ゼロ値。逆参照は nullポインター逆参照と見なされますが、0["hello"]
のように記述すると、"hello"[0]
(つまり、"h"
)。したがって、攻撃者が中括弧の間の式を制御する場合、攻撃でnullポインターの逆参照が使用される可能性があります(状況に応じて)。
fubar
事; memset(&fubar, UCHAR_MAX, sizeof fubar);
とすると、fubar
はすべて1ビットになります。つまり、アドレスである可能性があります これは、システムが(理論的に)対応できる最大のアドレスです。fubar[1]
にアクセスするとどうなりますか?最大のアドレスの後の要素にアクセスするにはどうすればよいですか?アドレスはその後ラップアラウンドしますか?技術的には、これはすべて未定義の動作ですが、一般的なアーキテクチャで 名前を付けると、次のようになります。
- の算術オーバーフローポインタ、それにつながる…
- Nullポインタの逆参照、および/または潜在的にバッファアンダーフロー。
memcpy
のバッファアンダーフローはリモートコード実行を許可しますか?
バッファアンダーフローにより、攻撃者は問題の配列の前のメモリ領域にある関数ポインタを上書きする可能性があります。これらの関数ポインタがシェルコードを指すようになっている場合、そのシェルコードは後で呼び出されたときに実行されます。
このややあいまいなコードでは、「int
の幅が広い場合にバッファアンダーフローのリスクがあるように見えます。 uint32_t
よりもドメイン。ntohl(string.st.len)+1
を使用すると、uint32_t
の値がint
タイプ。たとえば、INT_MIN
が-4294967296
(0 - UINT32_MAX
より1つ小さい)である場合を考えてみます。 INT_MAX
は4294967295
です…これは基本的に33ビットのint
です。バイトの幅までパディングするパディング。珍しいですが、可能です。この状況では、式ntohl(string.st.len)+1
はタイプがuint32_t
ではありません。タイプはint
であり、符号なし整数オーバーフローが発生したときに0にラップバックするのではなく、おそらく-4294967296
符号付き整数オーバーフローが発生した場合。
バッファアンダーフローに対する保証を探している場合は、整数リテラルサフィックス(つまり、ntohl(string.st.len)+1U
)。その場合、式はuint32_t
またはunsigned int
のいずれかになります(どちらのタイプが最大かによって異なります)。ドメイン)。
ntohl(string.st.len)
がその符号なし型の最大値(それが何であれ)よりも1つ小さい値を返す可能性があると考える場合は、len=ntohl(string.st.len)+1
は最大値になり、malloc(len+1)
は unsigned wrapping を引き起こすため、、次にcommand[len]=0
は、配列の終わりを超えて正しく書き込みます。その後、もちろん、また memcpy(command,string.st.data,len);
に問題が発生します(これはバッファオーバーフローです)。
バッファアンダーフローとオーバーフローだけがリスクではありません。 しない場合は、malloc
と
はNULL
を返し、nullポインターの逆参照を使用して任意のコードを実行できます。これは、
が失敗して発信者に返されます。これは、同じ方法を使用して、ラッピングの問題を確認して発信者に通知できることも意味します。
command[len] = 0
長さlen
のバッファの最大インデックスはlen-1
であるため、これはバッファオーバーフローです。または、実際のコードがmalloc(len)
ではなくmalloc(len+1)
を実行する場合は、の値を
0xFFFFFFFF
に設定します。len+1
を割り当てるので、0への設定は有効であるはずです。string.st.len
を‑1に設定することについて話していました。