「!xxx%s%s%s%s%s%s%s%s」の特別な点は何ですか?

「!xxx%s%s%s%s%s%s%s%s」の特別な点は何ですか?

私はつながっていますUnix嫌悪者のハンドブックそして偶然発見した内容は次のとおりです(149ページ)。

トピック:関連Unixのバグ

1991年10月11日

W4115x同級生—

アクティベーションレコード、パラメータ渡し、および呼び出しルールについて話している間に、次のように入力する必要があることをご存知でしたか?

!xxx%s%s%s%s%s%s%s%s

Cシェルはすぐにクラッシュしますか?理由をご存知ですか?

考える質問:

  • と入力するとシェルは何をしますか!xxx
  • 入力したときに入力した内容とはどのような関係がありますか !xxx%s%s%s%s%s%s%s%s
  • これがシェルをクラッシュさせるのはなぜですか?
  • この問題を回避するために、シェルの問題のある部分をどのように(かなり簡単に)書き換えることができますか?

ただ気になって問題が何なのか説明できる人はいますか?もちろん、Googleで文字列を検索しても役に立ちませんでした。メッセージから別の参照を検索すると、メッセージの他のコピーのみが提供され、説明は提供されません。

答え1

25年前の貝殻の由来を掘りたくはないが

それフォーマット文字列の脆弱性

シェルに次のコードが含まれている場合

printf(str);

strユーザー入力から取得した文字列はどこにあり、その内容はprintf使用された形式文字列になります。印刷引数が指す文字列を示します%sprintf引数が指定されていない場合(上記のようにフォーマット文字列のみ)、関数はスタックからいくつかの追加データを読み取り、それをポインタに従います。マップされていないメモリにアクセスすると、プロセスが中断される可能性があります。

ある程度メッセージのフレーズもそのような解決策を示唆していると思います。たとえば、と入力すると、!xxxシェルは明らかにエラーメッセージを表示します!xxx: event not found。そこでprintを試すことは大きな飛躍ではなく、!xxx%s%s%s%s%s%s%s%s: event not foundこれは型文字列の脆弱性を意味します。


私はこれをしなければなりませんでしたが、ソースコードを見てください。ここ( 4.3BSD-Tahoe/usr/src/bin/csh、 1988年から)。

findev(cp, anyarg)存在するsh.lex.c一致する歴史的出来事を見つける関数のようです。関連付けられたstruct Hist呼び出しのリストを繰り返しますHistlist。何も見つからない場合をseterr2(cp, ": Event not found");呼び出しますnoev()cpここでは、履歴から文字列を検索するようです。

seterr2()変数をerrパラメータの接続として設定し、複数の場所でerr使用します。if (err) error(err);process()sh.c。最後にerror()sh.err.c) には典型的な形式文字列の脆弱性が含まれています。if (s) printf(s, arg), printf(".\n");

他の場所ではerror()引数とともに呼び出されます(例:)。したがって、最初の引数が型文字列である可能性があるerror("Unknown user: %s", gpath + 1);という考えは明らかです。error()

記録交換機能を完全に理解したと言えば不正直なのです。 Cでコメントされていない手動文字列処理。これは歴史的置換では特別な意味を持ちますが、最初の文字%(たとえば)が呼び出された!%後にのみ特別に処理されることがわかります。findev()

関連情報