Common Gateway Interface

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

コンピューティングでは、Common Gateway InterfaceCGI )は、 Webサーバーが外部プログラムを実行できるようにするインターフェイス仕様であり、通常はユーザー要求を処理します。[1]

このようなプログラムは、多くの場合、スクリプト言語で記述されており、一般にCGIスクリプトと呼ばれますが、コンパイルされたプログラムが含まれる場合もあります。[2]

一般的な使用例は、WebユーザーがCGIを使用するWebページでWebフォームを送信する場合に発生します。フォームのデータは、CGIスクリプトを示すURLを使用してHTTPリクエスト内でWebサーバーに送信されます。次に、Webサーバーは新しいコンピュータープロセスでCGIスクリプトを起動し、フォームデータを渡します。CGIスクリプトの出力(通常はHTML形式)は、スクリプトによってWebサーバーに返され、サーバーはブラウザーの要求への応答としてそれをブラウザーに中継します。[3]

1990年代初頭に開発されたCGIは、Webページをインタラクティブにするために利用できる最も初期の一般的な方法でした。まだ使用されていますが、CGIは新しいテクノロジーと比較して比較的非効率的であり、主にそれらに置き換えられています。[4] [信頼できない情報源?]

歴史

スペック発表からの公式CGIロゴ

1993年に、米国立スーパーコンピュータ応用研究所(NCSA)チームは、www-talkメーリングリストにコマンドライン実行可能ファイルを呼び出すための仕様を作成しました。[5] [6] [7]他のWebサーバー開発者がそれを採用し、それ以来、Webサーバーの標準となっています。Ken Coarが議長を務める作業グループは、CGIのNCSA定義をより正式に定義するために、1997年11月に開始されました。[8]この作業の結果、CGIバージョン1.1を指定するRFC3875が作成されました。RFCで具体的に言及されているのは、次の貢献者です。[3]

歴史的に、CGIプログラムはしばしばC言語を使用して書かれていました。RFC 3875「CommonGatewayInterface(CGI)」は、環境変数が「Cライブラリルーチンgetenv()または変数environによってアクセスされる」と言って、 Cを使用してCGIを部分的に定義します[3] 。

CGIという名前は、 Webマスターがデータベースなどのレガシー情報システムをWebサーバーに接続したいと考えていたWebの初期の頃に由来しています。CGIプログラムは、Webサーバーとレガシー情報システムの間に共通の「ゲートウェイ」を提供するサーバーによって実行されました。

CGI仕様の目的

Webサーバーは、 Webブラウザからの要求に応答するHTTPサーバーソフトウェアを実行します通常、HTTPサーバーにはディレクトリ(フォルダー)があり、これはドキュメントコレクションとして指定されます。このサーバーに接続されているWebブラウザーに送信できるファイルです。[9]たとえば、Webサーバーにドメイン名があり、そのドキュメントコレクションがローカルファイルシステムに保存されている場合、Webサーバーはブラウザに(事前に作成された)ファイルを送信することで要求に応答します。 example.com/usr/local/apache/htdocs/http://example.com/index.html/usr/local/apache/htdocs/index.html

オンザフライで作成されたページの場合、サーバーソフトウェアは、プログラムを分離する要求を延期し、結果を要求元のクライアント(通常、ページをエンドユーザーに表示するWebブラウザー)に中継する場合があります。Webの初期の頃、そのようなプログラムは通常小さく、スクリプト言語で書かれていました。したがって、それらはスクリプトとして知られていました。

このようなプログラムでは通常、リクエストで指定する追加情報が必要です。たとえば、ウィキペディアがスクリプトとして実装されている場合、スクリプトが知っておく必要があることの1つは、ユーザーがログインしているかどうか、およびログインしている場合はどの名前でログインしているかです。ウィキペディアページの上部にあるコンテンツは、この情報に依存しています。

HTTPは、ブラウザがそのような情報をWebサーバーに渡す方法を提供します(URLの一部としてなど)。サーバーソフトウェアは、この情報を何らかの方法でスクリプトに渡す必要があります。

逆に、戻ったときに、スクリプトは、リクエストへの応答にHTTPが必要とするすべての情報(リクエストのHTTPステータス、ドキュメントコンテンツ(利用可能な場合)、ドキュメントタイプ(HTML、PDF、プレーンテキストなど))を提供する必要があります。 、など。

最初は、サーバーソフトウェアが異なれば、この情報をスクリプトと交換する方法も異なります。その結果、交換される情報が同じであっても、異なるサーバーソフトウェアに対して変更なしで機能するスクリプトを作成することはできませんでした。したがって、この情報を交換する方法を指定することにしました。CGI(サーバーソフトウェアがスクリプトとインターフェイスするための一般的な方法を定義するため、 Common Gateway Interface )。CGI仕様に従って動作するサーバーソフトウェアによって呼び出されるWebページ生成プログラムは、CGIスクリプトと呼ばれます。

この仕様はすぐに採用され、 ApacheIIS、および(拡張子付きの)node.jsベースのサーバー などのすべての有名なサーバーソフトウェアで引き続きサポートされています。

CGIスクリプトの初期の使用は、フォームを処理することでした。HTMLの初期には、HTMLフォームには通常、「アクション」属性と「送信」ボタンとして指定されたボタンがありました。送信ボタンが押されると、「アクション」属性で指定されたURIが、クエリ文字列として送信されたフォームからのデータとともにサーバーに送信されます「アクション」がCGIスクリプトを指定している場合、CGIスクリプトが実行され、HTMLページが生成されます。

CGIスクリプトの使用

Webサーバーを使用すると、所有者はどのURLをどのCGIスクリプトで処理するかを構成できます。

これは通常、ドキュメントコレクション内の新しいディレクトリをCGIスクリプトを含むものとしてマークすることによって行われます。その名前は多くの場合cgi-binです。たとえば/usr/local/apache/htdocs/cgi-bin、Webサーバー上のCGIディレクトリとして指定できます。WebブラウザがCGIディレクトリ内のファイル(たとえば)を指すURLを要求すると、http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=stringそのファイル()を単に/usr/local/apache/htdocs/cgi-bin/printenv.plWebブラウザに送信する代わりに、HTTPサーバーは指定されたスクリプトを実行し、スクリプトの出力を渡します。 Webブラウザに。つまり、スクリプトが標準出力に送信するものはすべて、ターミナルウィンドウの画面に表示されるのではなく、Webクライアントに渡されます。

上記のように、CGI仕様は、リクエストで渡される追加情報がスクリプトに渡される方法を定義します。たとえば、スクリプトの名前(この例では)の直後にスラッシュと追加のディレクトリ名がURLに追加された場合、/with/additional/pathそのパスはスクリプトが呼び出される前にPATH_INFO 環境変数に格納されます。パラメータがHTTPGETリクエスト(URLに疑問符が追加され、その後にparam = valueのペアが続く、例では)を介してスクリプトに送信される場合、スクリプトが呼び出される前に、?and=a&query=stringそれらのパラメータが環境変数に格納されます。QUERY_STRINGパラメータがHTTPPOSTリクエストを介してスクリプトに送信される場合、それらはスクリプトの標準入力に渡されます次に、スクリプトはこれらの環境変数またはデータを標準入力から読み取り、Webブラウザーの要求に適応させることができます。[10]

次のPerlプログラムは、Webサーバーによって渡されるすべての環境変数を示しています。

#!/ usr / bin / env perl

= head1説明

printenv —環境を出力するだけのCGIプログラム

= cut 
print  "Content-Type:text / plain \ n \ n" ;

 私の $ var   ソートキー %ENV  { printf " %s = \"%s \ "\ n" $ var $ ENV { $ var }; }  
       

Webブラウザがで環境変数の要求を発行すると、cygwinhttp://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encodingを実行している64ビットのWindows 7Webサーバーは次の情報を返します。

COMSPEC = "C:\ Windows \ system32 \ cmd.exe" 
DOCUMENT_ROOT = "C:/ Program Files(x86)/ Apache Software Foundation / Apache2.4 / htdocs" 
GATEWAY_INTERFACE = "CGI / 1.1" 
HOME = "/ home / SYSTEM " 
HTTP_ACCEPT = " text / html、application / xhtml + xml、application / xml; q = 0.9、* / *; q = 0.8 " 
HTTP_ACCEPT_CHARSET = " ISO-8859-1、utf-8; q = 0.7、*; q = 0.7 " 
HTTP_ACCEPT_ENCODING = " gzip、deflate、br " 
HTTP_ACCEPT_LANGUAGE = " en-us、en; q = 0.5 " 
HTTP_CONNECTION = " keep-alive " 
HTTP_HOST = " example.com " 
HTTP_USER_AGENT = " Mozilla / 5.0(Windows NT 6.1; WOW64; rv:67。0)Gecko / 20100101 Firefox / 67.0 "
パス="/ home / SYSTEM / bin:/ bin:/ cygdrive / c / program〜2 / php:/ cygdrive / c / windows / system32:..." 
PATHEXT = ".COM; .EXE; .BAT; .CMD; .VBS; .VBE; .JS; .JSE; .WSF; .WSH; .MSC " 
PATH_INFO = " / foo / bar " 
PATH_TRANSLATED = " C:\ Program Files(x86)\ Apache Software Foundation \ Apache2.4 \ htdocs \ foo \ bar " 
QUERY_STRING = " var1 = value1&var2 = with %2 0percent %2 0encoding " 
REMOTE_ADDR = " 127.0.0.1 " 
REMOTE_PORT = " 63555 " 
REQUEST_METHOD = " GET " 
REQUEST_URI = " /cgi-bin/printenv.pl/foo / bar?var1 = value1&var2 = with %2 0percent %2 0encoding "
SCRIPT_FILENAME ="C:/ Program Files(x86)/ Apache Software Foundation / Apache2.4 / cgi-bin / printenv.pl" 
SCRIPT_NAME = "/cgi-bin/printenv.pl" 
SERVER_ADDR = "127.0.0.1" 
SERVER_ADMIN = "(server管理者の電子メールアドレス) " 
SERVER_NAME = " 127.0.0.1 " 
SERVER_PORT = " 80 " 
SERVER_PROTOCOL = " HTTP / 1.1 " 
SERVER_SIGNATURE = " " 
SERVER_SOFTWARE = " Apache / 2.4.39(Win32)PHP / 7.3.7 " 
SYSTEMROOT = " C: \ Windows " 
TERM = " cygwin " 
WINDIR = " C:\ Windows "

これらの変数のすべてではありませんが、一部はCGI標準によって定義されています。PATH_INFO、、QUERY_STRINGおよびで始まるものなどの一部はHTTP_、HTTPリクエストから情報を渡します。

環境から、WebブラウザはWindows 7 PCで実行されているFirefoxであり、WebサーバーはUnixをエミュレートするシステムで実行されているApacheであり、CGIスクリプトの名前はです。 cgi-bin/printenv.pl

その後、プログラムは任意のコンテンツを生成し、それを標準出力に書き込むことができ、Webサーバーはそれをブラウザーに送信します。

以下は、CGIプログラムに渡される 環境変数です。

  • サーバー固有の変数:
  • 特定の変数をリクエストする:
    • SERVER_PROTOCOL:HTTP /バージョン
    • SERVER_PORTTCPポート(10進数)。
    • REQUEST_METHOD:HTTPメソッドの名前(上記を参照)。
    • PATH_INFO:プログラム名とスラッシュの後にURLに追加された場合は、パスサフィックス。
    • PATH_TRANSLATED:存在する場合、サーバーが想定する対応するフルパスPATH_INFO
    • SCRIPT_NAME:のようなプログラムへの相対パス/cgi-bin/script.cgi
    • QUERY_STRING:URLの後の部分キャラクター。クエリ文字列は、 HTMLアプリケーション/ x-www-formで定義されているGETメソッドを介して転送されたフォームデータを送信するために使用される場合、アンパサンドで区切られた* name =のペアvar1 = val1 var2 = val2 ...など)で構成されます。 -urlencoded
    • REMOTE_HOST:クライアントのホスト名。サーバーがそのようなルックアップを実行しなかった場合は設定を解除します。
    • REMOTE_ADDR:クライアントのIPアドレス(ドット10進数)。
    • AUTH_TYPE:該当する場合、識別タイプ。
    • REMOTE_USER特定のに使用されAUTH_TYPEます。
    • REMOTE_IDENTサーバーがそのようなルックアップを実行した場合にのみ、identを参照してください。
    • CONTENT_TYPEHTTPヘッダーを介して提供される、PUTまたはPOSTメソッドが使用される場合の入力データのインターネットメディアタイプ。
    • CONTENT_LENGTH:同様に、 HTTPヘッダーを介して提供された場合の入力データのサイズ(10進数、オクテット単位)。
    • ユーザーエージェントによって渡される変数(、、、、HTTP_ACCEPTおよび場合によっては他の変数)にHTTP_ACCEPT_LANGUAGE、対応するHTTPヘッダーの値が含まれているため、同じ意味を持ちます。HTTP_USER_AGENTHTTP_COOKIE

プログラムは、ヘッダーと空白行で始まる標準出力の形式で結果をWebサーバーに返します

ヘッダーはHTTPヘッダーと同じ方法でエンコードされ、返されるドキュメントのMIMEタイプを含める必要があります。[11] Webサーバーによって補足されたヘッダーは、通常、応答とともにユーザーに転送されます。

これは、Python 3で記述された単純なCGIプログラムと、単純な加算の問題を処理するHTMLです。[12]

add.html

<!DOCTYPE html> 
< html > 
 < body > 
  < form  action = "add.cgi"  method = "POST" > 
   < fieldset > 
     <凡例>追加する2つの数値を入力</ legend > 
     < label >最初の数値:<入力 タイプ= "number"  name = "num1" > </ label > <br /> < label >2番目の数値:<入力タイプ
      = "number"  name = "num2" > </ label > <br /> </ fieldset > < button > Add < / button > </ form > </ body > </ html >
   
   
  
 

add.cgi

#!/ usr / bin / env python3

 cgi  cgitbcgitbを
インポートしますenable ()

input_data  =  cgi FieldStorage ()

print 'Content-Type:text / html'  #HTMLは次の
print ''                          #空白行を残す
print '<h1>追加結果</ h1>' 
try 
    num1  =  int input_data [ "num1 " ] .value)num2 = int input_data [ " num2 " ] 。value except 
    print ' <output>申し訳ありませんが、スクリプトは入力を数値(整数)に変換できません。</ output >'   

    
    raise  SystemExit 1 
print '<output> {0} + {1} = {2} </ output>' .format num1 num2  num1  +  num2  

このPython3 CGIプログラムは、HTMLから入力を取得し、2つの数値を加算します。

展開

CGIをサポートするWebサーバーは、CGIスクリプトへの参照として機能するURLを解釈するように構成できます。一般的な規則は、ディレクトリツリーのベースにcgi-bin/ ディレクトリを置き、このディレクトリ内のすべての実行可能ファイル(セキュリティのために他のファイルは含まない)をCGIスクリプトとして扱うことです。もう1つの一般的な規則は、ファイル名拡張子を使用することです。たとえば、CGIスクリプトに常に拡張子が付けられている場合、.cgiそのようなすべてのファイルをCGIスクリプトとして解釈するようにWebサーバーを構成できます。便利で、多くの事前にパッケージ化されたスクリプトで必要ですが、リモートユーザーが適切な拡張子を持つ実行可能コードをアップロードできる場合、サーバーを開いて攻撃します。

HTTP PUTまたはPOSTの場合、ユーザーが送信したデータは、標準入力を介してプログラムに提供されますWebサーバーは、渡される 環境変数のサブセットを作成し、HTTP環境に関連する詳細を追加します。

を使用します

CGIは、ユーザーからの入力情報を処理し、適切な出力を生成するためによく使用されます。CGIプログラムの例は、wikiを実装するものです。ユーザーエージェントがエントリの名前を要求すると、WebサーバーはCGIプログラムを実行します。CGIプログラムは、そのエントリのページのソース(存在する場合)を取得し、それをHTMLに変換して、結果を出力します。Webサーバーは、CGIプログラムからの出力を受信し、それをユーザーエージェントに送信します。次に、ユーザーエージェントが[ページの編集]ボタンをクリックすると、CGIプログラムはHTMLtextareaまたはその他の編集コントロールにページのコンテンツを入力します。最後に、ユーザーエージェントが[ページの公開]ボタンをクリックすると、CGIプログラムは更新されたHTMLをそのエントリのページのソースに変換して保存します。

セキュリティ

CGIプログラムは、デフォルトでWebサーバーのセキュリティコンテキストで実行されます。最初に導入されたとき、新しいCGIを利用するためにシェルスクリプトまたはCプログラムをコーディングする方法を示すために、NCSA、Apache、およびCERNWebサーバーのリファレンスディストリビューションとともに多数のサンプルスクリプトが提供されました。そのようなスクリプト例の1つは、単純な電話帳を実装したPHFと呼ばれるCGIプログラムでした。

当時の他の多くのスクリプトと共通して、このスクリプトは次の関数を使用していましたescape_shell_cmd()この関数は、ユーザー入力から取得した引数をサニタイズし、その入力をUnixシェルに渡して、Webサーバーのセキュリティコンテキストで実行することになっています。スクリプトはすべての入力を正しくサニタイズせず、新しい行をシェルに渡すことができたため、複数のコマンドを効果的に実行できました。これらのコマンドの結果は、Webサーバーに表示されました。Webサーバーのセキュリティコンテキストで許可されている場合、攻撃者は悪意のあるコマンドを実行する可能性があります。

これは、新しいタイプのWebベースの攻撃の最初の広範な例であり、WebユーザーからのサニタイズされていないデータがWebサーバー上でのコードの実行につながる可能性があります。サンプルコードはデフォルトでインストールされていたため、攻撃は広範囲に及び、1996年の初めに多くのセキュリティアドバイザリにつながりました。[13]

代替案

着信HTTP要求ごとに、Webサーバーはそれを処理するための新しいCGIプロセスを作成し、HTTP要求が処理された後にCGIプロセスを破棄します。プロセスの作成と破棄は、プロセスの出力を生成する実際の作業よりもはるかに多くのCPUとメモリを消費する可能性があります。特に、CGIプログラムを仮想マシンで解釈する必要がある場合はなおさらです。多数のHTTPリクエストの場合、結果として生じるワークロードはWebサーバーをすぐに圧倒する可能性があります。

CGIプロセスの作成と破棄に伴うオーバーヘッドは、次の手法によって削減できます。

  • 仮想マシンによって解釈されるCGIプログラム( PerlPHPPythonプログラムなど)ではなく、マシンコードにプリコンパイルされたCGIプログラム(たとえば、CまたはC ++プログラムからプリコンパイルされたもの) 。
  • Apacheモジュールmod_perlmod_phpmod_pythonなど)、NSAPIプラグイン、ISAPIプラグインなどのWebサーバー拡張機能。複数の要求を処理し、Webサーバー内でホストされる長時間実行アプリケーションプロセスを可能にします。Web 2.0を使用すると、HTMLフォームを使用せずに、またユーザーに気付かれることなく、クライアントからサーバーにデータを転送できます。[14]
  • FastCGISCGI、およびAJPは、Webサーバーの外部でホストされている複数の要求を処理する長時間実行アプリケーションプロセスを可能にします。各アプリケーションプロセスはソケットをリッスンします。WebサーバーはHTTP要求を処理し、別のプロトコル(FastCGI、SCGI、またはAJP)を介して動的コンテンツの場合のみソケットに送信しますが、静的コンテンツは通常Webサーバーによって直接処理されます。このアプローチでは、必要なアプリケーションプロセスが少ないため、Webサーバー拡張アプローチよりも消費されるメモリが少なくなります。また、アプリケーションプログラムをWebサーバー拡張機能に変換するのとは異なり、FastCGI、SCGI、およびAJPアプリケーションプログラムはWebサーバーから独立したままです。
  • Jakarta EEは、 WebコンテナでJakartaサーブレットアプリケーションを実行して、動的コンテンツとオプションで静的コンテンツを提供します。これにより、プロセスの作成と破棄のオーバーヘッドが、スレッドの作成と破棄のはるかに低いオーバーヘッドに置き換えられますまた、使用中のJakartaEEのバージョンが基づいているJavaSEに付属するライブラリにプログラマーを公開します

Webアプリケーションの最適な構成は、アプリケーション固有の詳細、トラフィックの量、およびトランザクションの複雑さによって異なります。これらのトレードオフを分析して、特定のタスクと時間の予算に最適な実装を決定する必要があります。Webフレームワークは、CGIスクリプトを使用してユーザーエージェントと対話する代わりの方法を提供します。

も参照してください

参考文献

  1. ^ ロビンソン<[email protected]>、デビッド。「CommonGatewayInterface(CGI)バージョン1.1」tools.ietf.org 2021年2月16日取得
  2. ^ ロビンソン<[email protected]>、デビッド。「CommonGatewayInterface(CGI)バージョン1.1」tools.ietf.org2007年2月11日にオリジナルからアーカイブされました2021年2月16日取得
  3. ^ a b c "RFC3875:Common Gateway Interface(CGI)バージョン1.1"
  4. ^ Trieloff、Lars(2017年1月5日)。「2017:cgi-binの年…er、サーバーレス」ミディアム2021年2月16日取得
  5. ^ McCool、Rob(1993年11月14日)。「サーバースクリプト」www-talk(メーリングリスト)2019年5月15日取得
  6. ^ 「共通ゲートウェイインターフェース」Hoohoo NCSAHTTPdNCSA2010年1月27日にオリジナルからアーカイブされました。
  7. ^ 「CGI:CommonGatewayInterface」W3CWorld WideWebコンソーシアム2019年5月15日取得
  8. ^ 「CommonGatewayInterfaceRFCプロジェクトページ」2013年8月25日にオリジナルからアーカイブされました。
  9. ^ 「ファイルシステムの場所へのURLのマッピングApacheHTTPServerバージョン2.2」
  10. ^ ネルソン、アン・フルチャー、ネルソン、ウィリアム・ハリス・モアヘッド。(2001)。Webデータベース構築による電子商取引の構築。マサチューセッツ州ボストン:アディソンウェスリー。
  11. ^ 「CGI入門書(citycat.ruのミラー)」
  12. ^ 「AbaclesHTMLフォーム」www.abacles.com2016年4月19日にオリジナルからアーカイブされました2016年4月6日取得
  13. ^ 「phfCGIスクリプトは改行文字に対する保護に失敗します」ソフトウェアエンジニアリングインスティテュートCERTコーディネーションセンター2019年11月21日取得
  14. ^ Enrico Marino(2018年9月11日)。分散Webでの情報管理(PDF)(phd)。ローマトレ大学2019年2月11日取得

外部リンク