web-dev-qa-db-ja.com

strncpyが安全でないのはなぜですか?

Strncpyが安全でないと考えられる理由を探しています。これについてのドキュメントやそれを使用するエクスプロイトの例はありますか?

64
stimms

このサイト ;をご覧ください。それはかなり詳細な説明です。基本的に、strncpy()はNUL終了を必要としないため、さまざまな悪用の影響を受けやすくなります。

39
Tim

元の問題は、明らかに strcpy(3)メモリセーフな操作 ではなかったため、攻撃者がバッファ上の文字列を提供してスタック上のコードを上書きする可能性があることです。 、注意深く配置された場合、攻撃者から任意のコードを実行する可能性があります。

しかし、 strncpy(3) には、宛先ですべての場合にヌル終了を提供しないという別の問題があります。 (ソースストリングが宛先バッファーよりも長いことを想像してください。)将来の操作では、結果がさらに3番目のバッファーにコピーされると、同じサイズのバッファー間でCヌル終端文字列が適合するとダウンストリームが誤動作する可能性があります。

Strncpy(3)の使用はstrcpy(3)よりも優れていますが、strlcpy(3)のようなものの方が優れています。

12
DigitalRoss

Strncpyを安全に使用するには、(1)結果バッファにヌル文字を手動で貼り付けるか、(2)バッファが事前にヌルで終わることを知って、(length-1)をstrncpyに渡すか、(3)バッファーの長さをバッファーの長さにバインドしないメソッドを使用して、バッファーがコピーされることはありません。

Strncpyは、コピーされた文字列を超えてバッファー内のすべてをゼロで埋めるが、他の長さ制限のあるstrcpyバリアントはそうではないことに注意することが重要です。これは場合によってはパフォーマンスの低下になる可能性がありますが、セキュリティ上の利点になる場合もあります。たとえば、strlcpyを使用して「supercalifragilisticexpalidocious」をバッファにコピーし、次に「it」をコピーすると、バッファは「it ^ ercalifragilisticexpalidocious ^」を保持します(「^」を使用して0バイトを表します)。バッファが固定サイズの形式にコピーされると、追加のデータがタグとともにタグ付けされる場合があります。

7
supercat

質問は「ロードされた」前提に基づいているため、質問自体が無効になります。

ここで一番下の行は、strncpyが安全でないと見なされておらず、安全であると見なされたことがないことです。その機能に付加できる「不安定性」の唯一の主張は、CメモリーモデルとC言語自体の一般的な不安の広範な主張です。 (しかし、それは明らかに完全に異なるトピックです)。

C言語の領域内では、strncpyに内在するある種の「不安」の誤った信念は、「安全な文字列のコピー」にstrncpyを使用する広範な疑わしいパターンに由来します。しませんし、意図されていません。そのような使用法は確かに非常にエラーを起こしやすいです。ただし、「非常にエラーが発生しやすい」と「安全でない」の間に等号を付けたとしても、strncpyの問題ではなく、使用上の問題(つまり、教育の問題)です。

基本的に、strncpyの唯一の問題は不幸な命名であると言うことができます。これは初心者プログラマーが実際に仕様を読む代わりにこの関数が何をするかを理解していると仮定させます。無能なプログラマーは関数名を見ると、strncpystrcpyの「安全なバージョン」であると想定していますが、実際にはこれら2つの関数は完全に無関係です。

一例として、除算演算子に対してまったく同じ主張を行うことができます。ほとんどの人が知っているように、C言語に関して最もよく聞かれる質問の1つは、「1/20.5に評価されると仮定しましたが、代わりに0を得ました。なぜですか?」それでも、言語初心者がその動作を誤解する傾向があるという理由だけで、除算演算子が安全でないとは主張しません。

別の例として、無能なプログラマーがしばしば出力が真にランダムではないという事実に不愉快に驚いているという理由だけで、疑似乱数ジェネレーター関数を「安全ではない」と呼びません。

これは、strncpy関数を使用した場合とまったく同じです。初心者プログラマーが疑似乱数ジェネレーターが実際に行うことを学ぶのに時間がかかるように、strncpyが実際に行うことを学ぶのに時間がかかります。 strncpy変換関数であり、ゼロ終端文字列を固定幅文字列に変換することを目的とすることを学ぶには時間がかかります。 strncpyが「安全な文字列コピー」とはまったく関係がなく、その目的に有意義に使用できないことを知るには時間がかかります。

確かに、語学の学生がstrncpyの目的を学ぶのは、除算演算子で物事を整理するよりもはるかに時間がかかります。ただし、これはstrncpyに対する「不安定な」クレームの基礎となります。

追伸受け入れられた答えにリンクされているCERT文書は、それだけに専念しています。strncpyの「安全な」バージョンとしてのstrcpy関数の典型的な無能な乱用の不安を示すためです。 strncpy自体が何らかの形で安全でないと主張することを意図したものではありません。

3
AnT

Git 2.19(2018年第3四半期)のpathcでは、strcat()などのシステムAPI関数を誤用するのは簡単すぎることがわかりました。 strncpy(); ...そして、このコードベースのこれらの機能を禁止します。

commit e488b7acommit cc8fdaecommit 1b11b64 (24 Jul 2018)、および commit c8af66a (2018年7月26日)を参照してください) Jeff King(peff によって。
C浜野潤夫-gitster- in commit e28daf2 、2018年8月15日)

_banned.h_:strcat()を禁止としてマーク

strcat()関数には、strcpy()と同じオーバーフロー問題がすべてあります。
また、ボーナスとして、その後の呼び出しごとに既存の文字列を処理する必要があるため、偶発的に2次的になりやすくなります。

最後のstrcat()呼び出しは f063d38 でなくなりました(デーモン:再スポーン時にcld-> env_arrayを使用、2015-09-24、Git 2.7.0)。
一般に、strcat()は、動的な文字列(strbufまたはxstrfmt)、またはxsnprintfで置き換えることができます。長さには制限があります。

1
VonC