セッションの仕組みとセキュリティの問題を詳しく解説(PHPサンプル解説)_PHPチュートリアル

WBOY
リリース: 2016-07-13 10:34:20
オリジナル
768 人が閲覧しました

まず、プロトコルのステートレスな性質を理解するために、http についての知識を簡単に理解しましょう。次に、Cookie に関する基本的な操作をいくつか学びます。最後に、いくつかのシンプルで効率的な方法を使用して、PHP アプリケーションのセキュリティと安定性を向上させる方法を段階的に説明します。

ほとんどの若手 PHP プログラマーは、PHP のデフォルトのセッション メカニズムのセキュリティが保証されているように見えると思うと思います。実際はその逆です。セキュリティに関しては、PHP チームはプログラマーが使用できる便利なセッション ソリューションのセットを提供しているだけです。 、それはアプリケーション開発チームの責任であるプログラマーによって強化される必要があります。いわば、多くの方法があるため、最善のものはなく、より良いものがあるだけです。攻撃方法は常に変化しており、守備側も常に戦術を変更する必要があるため、PHP チームのアプローチは比較的賢明であると個人的には思います。

1. HTTP ステートレス性

HTTP はステートレス プロトコルです。これは、このプロトコルではブラウザーが各リクエストで自身を識別する必要がなく、ブラウザーとサーバーが複数のページ間のアクセスのために永続的な接続を維持しないためです。ユーザーがサイトにアクセスすると、ユーザーのブラウザは http リクエストをサーバーに送信し、サーバーは http レスポンスをブラウザに返します。実際、これは非常に単純な概念であり、クライアントがリクエストを行い、サーバーが応答するという、http プロトコルに基づく通信プロセス全体が行われます。
Web アプリケーションは http プロトコルに基づいて通信するため、http はステートレスであることはすでに述べましたが、そのため Web アプリケーションの状態を維持することがさらに困難になり、開発者にとって大きな課題となります。 Cookie は http の拡張として生まれました。その主な目的は、http のステートレスな特性を補い、クライアントとサーバーの間で状態を維持する方法を提供することです。ただし、セキュリティ上の理由から、一部のユーザーでは Cookie が無効になっています。ブラウザ。この場合、ステータス情報は URL のパラメータを通じてのみサーバーに渡されますが、このメソッドのセキュリティは非常に貧弱です。実際、通常の考え方によれば、クライアントは自身を識別し、サーバーとの状態を維持する必要があります。ただし、セキュリティ上の理由から、クライアントからの情報は完全に信頼できるものではないということを誰もが理解する必要があります。
それにもかかわらず、Web アプリケーションの状態を維持する問題には比較的洗練された解決策があります。ただし、完璧な解決策はなく、どんなに優れた解決策であっても、すべての状況に適用できるわけではないことを言わなければなりません。この記事ではいくつかのテクニックを紹介します。これらのテクノロジーを使用すると、アプリケーションの状態をより安定して維持し、セッション ハイジャックなどのセッションに対する一部の攻撃に対抗できます。また、Cookie がどのように機能するか、PHP セッションが何を行うか、およびセッションをハイジャックする方法を学ぶことができます。

2. HTTP の概要

Web アプリケーションのステータスを維持し、最適なソリューションを選択するにはどうすればよいですか?この質問に答える前に、まず Web の基礎となるプロトコルであるハイパーテキスト転送プロトコル (HTTP) を理解する必要があります。

ユーザーがドメイン名 http://example.com にアクセスすると、ブラウザはサーバーとの tcp/ip 接続を自動的に確立し、http リクエストを example.com サーバーのポート 80 に送信します。このリクエストの文法は以下のとおりです:

コードをコピーします コードは次のとおりです:

GET / HTTP / 1.1
HOST: Example.org
🎜🎜 

以上第一行叫做请求行,第二个参数(一个反斜线在这个例子中)表示所请求资源的路径。反斜线代表了根目录;服务器会转换这个根目录为服务器文件系统中的一个具体目录。
Apache的用户常用DocumentRoot这个命令来设置这个文档根路径。如果请求的url是http://example.org/path/to/script.php,那么请求的路径就是/path/to/script.php。假如document root 被定义为usr/lcoal/apache/htdocs的话,整个请求的资源路径就是/usr/local/apache/htdocs/path/to/script.php。
第二行描述的是http头部的语法。在这个例子中的头部是Host, 它标识了浏览器希望获取资源的域名主机。还有很多其它的请求头部可以包含在http请求中,比如user-Agent头部,在php可以通过$_SERVER['HTTP_USER_AGENT']获取请求中所携带的这个头部信息。
但是遗憾的是,在这个请求例子中,没有任何信息可以唯一标识当前这个发出请求的客户端。有些开发者借助请求中的ip头部来唯一标识发出此次请求的客户端,但是这种方式存在很多问题。因为,有些用户是通过代理来访问的,比如用户A通过代理B连接网站www.example.com, 服务器端获取的ip信息是代理B分配给A的ip地址,如果用户这时断开代理,然后再次连接代理的话,它的代理ip地址又再次改变,也就说一个用户对应了多个ip地址,这种情况下,服务器端根据ip地址来标识用户的话,会认为请求是来自不同的用户,事实上是同一个用户。 还用另外一种情况就是,比如很多用户是在同一个局域网里通过路由连接互联网,然后都访问www.example.com的话,由于这些用户共享同一个外网ip地址,这会导致服务器认为这些用户是同一个用户发出的请求,因为他们是来自同一个ip地址的访问。
保持应用程序状态的第一步就是要知道如何来唯一地标识每个客户端。因为只有在http中请求中携带的信息才能用来标识客户端,所以在请求中必须包含某种可以用来标识客户端唯一身份的信息。Cookie设计出来就是用来解决这一问题的。

三、cookies

如果你把Cookies看成为http协议的一个扩展的话,理解起来就容易的多了,其实本质上cookies就是http的一个扩展。有两个http头部是专门负责设置以及发送cookie的,它们分别是Set-Cookie以及Cookie。当服务器返回给客户端一个http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。一个cookie的设置以及发送过程分为以下四步:

1.客户端发送一个http请求到服务器端
2.服务器端发送一个http响应到客户端,其中包含Set-Cookie头部
3.客户端发送一个http请求到服务器端,其中包含Cookie头部
4.服务器端发送一个http响应到客户端
这个通讯过程也可以用以下下示意图来描述:

セッションの仕組みとセキュリティの問題を詳しく解説(PHPサンプル解説)_PHPチュートリアル
 

クライアントの 2 番目のリクエストに含まれる Cookie ヘッダーは、クライアントを一意に識別するために使用できる情報をサーバーに提供します。このとき、サーバーはクライアントが Cookie を有効にしているかどうかも判断できます。ユーザーがアプリケーションとの対話中に突然 Cookie の使用を無効にする可能性はありますが、これは無視できるほどの可能性はなく、実際にこれが真実であることが証明されています。

4. データを取得して投稿します

クライアントは、Cookie に加えて、リクエストパラメータやリクエストパスなど、リクエストされた URL にサーバーに送信されるデータを含めることもできます。 例を見てみましょう:

コードをコピーします コードは次のとおりです:

GET /index.php?foo=bar HTTP/1.1
ホスト: example.org

上記は通常の http get リクエストです。get リクエストは、example.org ドメイン名に対応する Web サーバーの下のindex.php スクリプトに送信されます。index.php スクリプトでは、$_GET[ を通じて対応するものを取得できます。 'foo'] URL の foo パラメータの値、つまり 'bar'。ほとんどの PHP 開発者はこのようなデータを GET データと呼び、一部の開発者はクエリ データまたは URL 変数と呼びます。ただし、GET データは HTTP GET タイプのリクエストにのみ含めることができるということではなく、関連する GET データが HTTP POST タイプのリクエストに含めることもできます。つまり、GET データの配信は特定のリクエスト タイプに依存しません。

クライアントがサーバーにデータを渡すもう 1 つの方法は、http リクエストのコンテンツ領域にデータを含めることです。 このメソッドでは、リクエスト タイプが POST である必要があります。次の例を見てください。

コードをコピーします。 コードは次のとおりです。
POST /index.php HTTP/1.1
ホスト: example.org
Content-Type: application /x-www-form-urlencoded
Content-Length: 7

foo=bar


この場合、スクリプトindex.phpは$_POST[を呼び出すことで対応する値barを取得できます。 「フー」]。開発者はこのデータを POST データと呼びます。これはポスト モードでのよく知られたフォーム送信方法です。
, 1 つのリクエストに、これら 2 つの形式のデータを同時に含めることができます:


コードをコピー

コードは次のとおりです: post /index.php?myget=foo http /1.1
host: 例.orgContent-Type : application/x-www-form-urlencoded
Content-Length: 11

mypost=bar
[code]
これら 2 つのデータ送信方法は、Cookie を使用してデータを送信するよりも安定しています。無効ですが、GET メソッドと POST メソッドでデータを渡す場合にはこの状況は発生しません。次の例のように、http リクエスト URL に PHPSESSID を含めることができます:
[code]
GET /index.php?PHPSESSID=12345 HTTP/1.1
Host: example.org


この方法でセッション ID を渡すと、Cookie ヘッダーを使用してセッション ID を渡すのと同じ効果を得ることができますが、欠点は、開発者がセッション ID を URL に追加するか、フォームに追加する必要があることです。隠しフィールドとして。 Cookie とは異なり、サーバーがクライアントに Cookie を正常に作成するように指示している限り、クライアントは後続のリクエストで対応する期限切れになっていない Cookie を自動的にサーバーに渡します。もちろん、session.use_trans_sid をオンにすると、PHP はセッション ID を URL とフォームの隠しフィールドに自動的に追加することもできますが、セキュリティ上の問題があるため、このオプションをオンにすることはお勧めできません。この場合、たとえば、一部のユーザーが URL をブックマークしたり、URL を共有したりすると、セッション ID の有効期限が切れていない限り、セッション ID が漏洩する可能性があります。サーバー側では、セッション ID に加えて、ユーザーの正当性を検証するための他のメソッドも追加されます。

ただし、GET よりも POST でセッション ID を渡す方がはるかに安全です。ただし、この方法の欠点は、より面倒であることです。この場合、アプリケーションですべてのリクエストをポストリクエストに変換するのは明らかに適切ではないからです。

5. セッション管理

これまでは、アプリケーションの状態を維持する方法についてのみ説明し、リクエスト間の関係を維持する方法については簡単に触れただけでした。次に、実際によく使われるテクノロジーであるセッション管理について説明します。セッション管理に関しては、各リクエスト間の状態を維持するだけでなく、セッション中に特定のユーザーごとに使用されるデータを維持する必要もあります。このデータは特定のユーザーとサーバー間のセッションに関連付けられているため、このデータをセッション データと呼ぶことがよくあります。 PHP の組み込みセッション管理メカニズムを使用する場合、セッション データは通常サーバー側フォルダー /tmp に保存され、セッション データはスーパー配列 $_SESSION に自動的に保存されます。セッションを使用する最も簡単な例の 1 つは、関連するセッション データ (注: 実際に渡されるのはセッション ID) をあるページから別のページに渡すことです。以下では、サンプル コード 1、start.php を使用してこの例を示します。

サンプルコード 1 – start.php


コードをコピーします コードは次のとおりです:
?- -> $_SESSION['foo'] を通じて start.php で定義された値 'bar' を取得します。以下のサンプルコード 2 を見てください:
コード例 2-Continue.php




コードをコピーします。

& lt;-? Php
session_start ()
echo $ _Sactive ['foo'];
?-->

   
是不是非常简单,但是我要指出的话,如果你真的这样来写代码的话,说明你对php底层的对于session的实现机制还不是非常了解透彻。在不了解php内部给你自动做了多少事情的情况下,你会发现如果程序出错的话,这样的代码将变的很难调试,事实上,这样的代码也完全没有安全性可言。

六、session的安全性问题

一直以来很多开发者都认为php内置的session管理机制是具有一定的安全性,可以对一般的session攻击起到防御。事实上,这是一种误解,php团队只实现了一种方便有效的机制。具体的安全措施,应该有应用程序的开发团队来实施。 就像开篇谈到的,没有最好的解决方案,只有最合适你的方案。

现在,我们来看下一个比较常规的针对session的攻击:

1..用户访问http://www.example.org,并且登录。
2.example.org的服务器设置指示客户端设置相关cookie – PHPSESSID=12345
3.攻击者这时访问http://www.example.org/,并且在请求中携带了对应的cookie – PHPSESSID=12345
4.这样情况下,因为example.orge的服务器通过PHPSESSID来辨认对应的用户的,所以服务器错把攻击者当成了合法的用户。
整个过程的描述,请看下面的示例图:

セッションの仕組みとセキュリティの問題を詳しく解説(PHPサンプル解説)_PHPチュートリアル
 

もちろん、この攻撃方法の前提条件は、攻撃者が何らかの手段で正当なユーザーの PHPSESSID を修正、乗っ取り、または推測する必要があるということです。これは非常に難しいように思えますが、不可能ではありません。

7. セキュリティ強化

セッションのセキュリティを強化するために使用できる手法は数多くあります。主なアイデアは、正当なユーザーにとっては検証プロセスをできるだけ単純にし、攻撃者にとっては手順をできるだけ複雑にすることです。もちろん、これはバランスが難しいようで、アプリケーションの具体的な設計に基づいて決定する必要があります。

H http/1.1 で最も簡単に実行できるリクエストには、リクエスト行といくつかのホスト ヘッドが含まれます:


コードをコピー コードは次のとおりです:
GET/HTTP/1.1
Host: Example.org

Ifクライアント側 関連するセッション識別子を PHPSESSID 経由で渡すには、Cookie ヘッダーに PHPSESSID を含めることができます:

コードをコピーします コードは次のとおりです:
GET / HTTP/1.1
ホスト: example.org
Cookie: PHPSESSID =12345

同様に、クライアントはリクエストされた URL でセッション識別子を渡すこともできます。

コードをコピーします コードは次のとおりです:
GET /?PHPSESSID=12345
HTTP/1.1Host: example.org

もちろん、セッション識別子をPOSTデータに含めることもできます, しかし、これはユーザーエクスペリエンスに良い影響があるため、この方法はほとんど使用されません。
TCP/IP からの情報は完全には信頼できない可能性があるため、Web 開発者がセキュリティを強化するために TCP/IP の情報を使用することは適切ではありません。 ただし、攻撃者が正規のユーザーになりすましてシステムに侵入するには、正規のユーザーの一意の識別子も提供する必要があります。したがって、システムを保護する唯一の有効な方法は、セッション識別子を可能な限り隠すか、推測を困難にすることであると思われます。両方実装できれば一番良いのですが。

PHP はランダムなセッション ID を自動的に生成しますが、これは基本的に推測することが不可能であるため、この領域のセキュリティは引き続き保証されます。ただし、攻撃者による正規のセッション ID の取得を阻止することは非常に困難であり、基本的に開発者の制御の範囲を超えています。

実際、多くの状況でセッション ID の漏洩が発生する可能性があります。 たとえば、セッション ID が GET データを通じて渡される場合、この機密の ID 情報が漏洩する可能性があります。ユーザーによっては、電子メールのコンテンツ内のセッション ID を含むリンクをキャッシュ、保存、または送信する場合があるためです。 Cookie は比較的安全なメカニズムですが、ユーザーはクライアントで Cookie を無効にすることができます。一部の IE バージョンには重大なセキュリティ上の脆弱性もあります。最も有名なのは、セキュリティ上のリスクを伴う悪質なサイトに Cookie が漏洩することです。

したがって、開発者はセッション ID が推測できないことを確信できますが、攻撃者が特定の方法を使用してセッション ID を取得する可能性はあります。したがって、アプリケーションでそのような状況が発生しないように、追加のセキュリティ対策を講じる必要があります。

実際、標準の HTTP リクエストには、Host などの必須ヘッダーに加えて、いくつかのオプションのヘッダーも含まれています。例として、次のリクエストを見てください。


コードをコピーします コードは次のとおりです。
GET / HTTP/1.1
ホスト: example.org
Cookie: PHPSESSID=12345 ユーザーエージェント: Mozilla/5.0 (Macintosh; U; Intel Mac OS ecko/ 20061204 Firefox/2.0.0.1
アウトアウトアウトアウトアウトアウトアウト クリーン アウト – アウト アウト アウト アウト アウト アウト スルー mp 使用使用使用使用使用使用使用使用使用使用使用使用frommpfromfromLfromanceLancefromance out out outアウト・アウト・アウト・アウト・アウト・アウト・オフ・オフ - 言語: en


上記のリクエストの例には、User-Agent、Accept、Accept-Charset、および Accept-Language という 4 つの追加ヘッダーが含まれていることがわかります。これらのヘッダーは必須ではないため、アプリケーションで機能するためにこれらのヘッダーのみに依存するのは賢明ではありません。ただし、ユーザーのブラウザがこれらのヘッダーをサーバーに送信した場合、同じユーザーが同じブラウザを通じて送信する後続のリクエストにもこれらのヘッダーが含まれることは確実です。もちろん、特別な状況はほとんどありません。上記の例が、現在サーバーとセッションを行っているユーザーによって行われたリクエストである場合は、次のリクエストを検討してください:

б コードをコピーします。 コード コードは次のとおりです: GET/HTTP/1.1 HOST: Example.org
cookie: phpsessid = 12345
user-agent: Mozilla/5.0


リクエストの Cookie ヘッダーなので、同じphpセッションにアクセスします。ただし、リクエストの User-Agent ヘッダーは前のリクエストの情報と異なります。システムは 2 つのリクエストが同じユーザーによって行われたと想定できますか?
この場合、ブラウザのヘッダーが変更されたことを発見したが、これが攻撃者からのリクエストであるかどうかわからない場合、より良い対策は、ユーザーにパスワードの入力を求める入力ボックスをポップアップ表示することです。この場合、ユーザーエクスペリエンスへの影響は大きくなく、攻撃を効果的に防ぐことができます。

もちろん、例 3 のコードと同様に、システムの User-Agent ヘッダーをチェックするコードを追加することもできます: sampleコード3:

コピーコードは次のとおりです。最初のリクエストで、以下の例 4 のコードと同様に、MD5 アルゴリズムを使用してユーザー エージェント情報を暗号化し、セッションに保存する場合:


サンプルコード 4:

コードをコピーします
コードは次のとおりです:


);


User-Agent 情報の暗号化に MD5 を使用する必要はありませんが、この方法を使用した後に $_SERVER['HTTP_USER_AGENT'] データをフィルタリングする必要はありません。そうしないと、クライアントからのデータは信頼できないため、このデータを使用する前にデータ フィルタリングを実行する必要があるため、これには注意が必要です。

User-Agent クライアントのヘッダー情報を確認した後、攻撃者はセッションをハイジャックするための 2 つの手順を完了する必要があります。

1. 有効なセッション ID を取得する2. 偽装されたリクエストに同じ User-Agent ヘッダーが含まれる


攻撃者は実際に有効なセッション ID を取得できるため、そのレベルで偽装を作成することは難しくないと言えるでしょう。同一のユーザーエージェント。はい、しかし、これにより少なくとも多少の問題が追加され、セッション メカニズムのセキュリティもある程度強化されると言えます。

User-Agent ヘッダーをチェックしてセキュリティを強化できるため、他のヘッダー情報を使用して暗号化されたトークンを生成し、後でクライアントに使用させることもできます。リクエスト内のこのトークン!この場合、攻撃者がそのようなトークンがどのように生成されるかを推測することは基本的に不可能です。これは、スーパーマーケットでクレジット カードを使用して支払うのと同じです。クレジット カード (セッション ID など) が必要であり、これらの両方が満たされている場合にのみ、支払いパスワードも入力する必要があります。支払い用のアカウントを正常に入力できますか。 次のコードを見てください:
コードをコピーします

コードは次のとおりです:


gt;

注:これを受け入れる 一部のブラウザでは、ユーザーがブラウザを更新するとこのヘッダーが自動的に変更されるため、このヘッダーをトークンの生成に使用しないでください。

この非常に推測が難しいトークンを検証メカニズムに追加すると、セキュリティが大幅に向上します。このトークンがセッション ID のように渡される場合、この場合、攻撃者はユーザーのセッションをハイジャックするために必要な 3 つの手順を完了する必要があります:

1. 正当なセッション ID を取得します
2. 同じ User-Agent ヘッダーをリクエストに追加し、それを使用してトークンを生成します
3. 攻撃者のトークンをリクエストに含めます 4. ここに問題があります。セッション ID とトークンの両方が GET データを通じて渡される場合、セッション ID を取得できる攻撃者はトークンも取得できます。したがって、より安全で信頼性の高い方法は、2 つの異なるデータ転送方法を使用して、セッション ID とトークンをそれぞれ転送することです。たとえば、Cookie を介してセッション ID を渡し、GET データを介してトークンを渡します。したがって、攻撃者が何らかの手段でこの一意のユーザー ID を取得したとしても、同時にこのトークンを簡単に取得できる可能性は低く、依然として比較的安全です。

セッションメカニズムのセキュリティを強化するために使用できる技術的手段も多数あります。セッションの内部性質を大まかに理解した後、アプリケーション システムに適した検証メカニズムを設計して、システムのセキュリティを大幅に向上できることを願っています。結局のところ、あなたは開発中のシステムに最も精通しており、実際の状況に基づいて独自の追加のセキュリティ対策を実装できる開発者の 1 人です。



8. 概要

上記はセッションの動作メカニズムを簡単に説明し、いくつかのセキュリティ対策を簡単に説明しています。ただし、上記の方法はセキュリティを強化できますが、システムを完全に保護できるわけではないことに注意してください。関連するコンテンツは読者自身で調べてください。この研究プロセス中に、実践的に非常に価値のあるソリューションを学ぶことができると思います。

http://www.bkjia.com/PHPjc/751932.html

www.bkjia.com

本当

技術記事まず、プロトコルのステートレスな性質を理解するために、http についての知識を簡単に理解しましょう。次に、Cookie に関する基本的な操作をいくつか学びます。最後に、使い方をステップごとに説明します...
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート