ホームページ  >  記事  >  バックエンド開発  >  PHP_PHP チュートリアルを開発するときに注意する必要があるセキュリティの問題

PHP_PHP チュートリアルを開発するときに注意する必要があるセキュリティの問題

WBOY
WBOYオリジナル
2016-07-21 15:34:25824ブラウズ

PHP プログラマ、特に初心者は、インターネットの危険性について常にほとんど知識がありません。ハッカーがどのように侵入し、侵入し、脆弱性をアップロードし、SQL インジェクションやクロススクリプト攻撃を行うのかがわかりません。もっと。最も基本的な予防策として、外部からの送信に注意を払い、ファイアウォールに対処するための最初のセキュリティ メカニズムを作成する必要があります。

ルール 1: 外部データや入力を決して信頼しない

Web アプリケーションのセキュリティについて最初に認識しなければならないのは、外部データを信頼すべきではないということです。外部データには、プログラマが PHP コードに直接入力しないデータが含まれます。他のソースからのデータ (GET 変数、フォーム POST、データベース、構成ファイル、セッション変数、Cookie など) は、セキュリティを確保するための手順が講じられるまで信頼できません。

たとえば、次のデータ要素は PHP で設定されているため安全であると考えられます。

リスト 1. 安全で完璧なコード

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

$myUsername = 'tmyer'
$arrayarrayUsers = array('tmyer', 'tom', 'tommy ');
define("GREETING", 'Hello there' . $myUsername);

ただし、次のデータ要素には欠陥があります。


リスト 2. 安全でない欠陥のあるコード
コードをコピーする コードは次のとおりです。
$myUsername = $_POST['username'] //tainted! myUsername, 'tom', 'tommy'); //tainted!
define("GREETING", 'hello there' . $myUsername); なぜ最初の変数 $myUsername には欠陥があるのか? フォーム POST から直接取得されるためです。ユーザーはこの入力フィールドに任意の文字列を入力できます。これには、ファイルを駆除したり、以前にアップロードしたファイルを実行したりする悪意のあるコマンドも含まれます。 「A ~ Z の文字のみを受け入れるクライアント側 (JavaScript) フォーム検証スクリプトを使用すれば、この危険を回避できないのですか?」と疑問に思われるかもしれません。はい、これは常に有益なステップですが、後で説明するように、誰でも任意のフォームを自分のマシンにダウンロードして変更し、必要なものを再送信できます。

解決策は簡単です。$_POST['username'] でサニタイズコードを実行する必要があります。これを行わないと、(配列や定数などで) $myUsername を使用するたびに、これらのオブジェクトが汚染される可能性があります。ユーザー入力をサニタイズする簡単な方法は、正規表現を使用して処理することです。この例では、文字のみが受け入れられることが想定されています。文字列を特定の文字数に制限したり、すべての文字を小文字にすることを要求したりすることも良いアイデアかもしれません。


リスト 3. ユーザー入力を安全にする




コードをコピーします
コードは次のとおりです。
$myUsername = cleanInput($_POST['username']) //clean! = array ($myUsername, 'tom', 'tommy'); //clean! define("GREETING", 'hello there' . $myUsername); //clean! strto lower( $input); $clean = preg_replace(“/[^a-z]/”, “”, $clean); $clean = substr($clean,0,12); return $clean; >

ルール 2: セキュリティの実装を困難にする PHP 設定を無効にする


ユーザーの入力を信頼できないのと同じように、マシン上での PHP の構成方法も信頼すべきではないことも知っておく必要があります。たとえば、register_globals が無効になっていることを確認してください。 register_globals が有効な場合、$variable を使用して GET または POST 文字列を同じ名前に置き換えるなどの不注意な行為が可能になります。この設定を無効にすると、PHP は正しい名前空間の正しい変数を参照するように強制します。フォーム POST から変数を使用するには、$_POST['variable'] を引用符で囲む必要があります。こうすることで、この特定の変数を Cookie、セッション、または GET 変数と間違えることがなくなります。


ルール 3: 理解できない場合、保護することはできません

一部の開発者は、奇妙な構文を使用したり、ステートメントを非常にコンパクトに編成して、短くても曖昧なコードを形成します。このアプローチは効率的かもしれませんが、コードが何をしているのかを理解していないと、コードを保護する方法を決定できません。たとえば、以下の 2 つのコードのうち、どちらが好きですか? = (isset($_POST ['ユーザー名']) ? $_POST['ユーザー名']:”);
//難読化されていないコード $input = ”; isset($_POST['ユーザー名']){ $input = $_POST ['ユーザー名'];
}else{
$input = ”;
2 番目のより明確なコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります。

ルール 4: 「多層防御」は新しい魔法です

このチュートリアルでは、フォームを処理する PHP コードで必要な措置を講じながら、オンライン フォームを保護する方法を例を使用して説明します。同様に、PHP 正規表現を使用して GET 変数が完全に数値であることを確認する場合でも、SQL クエリでエスケープされたユーザー入力が使用されることを確認する手順を実行できます。多層防御は良いアイデアであるだけでなく、深刻な問題に巻き込まれないようにします。基本的なルールについて説明したので、最初の脅威である SQL インジェクション攻撃を見てみましょう。

◆SQL インジェクション攻撃を防ぐ

SQL インジェクション攻撃では、ユーザーはフォームまたは GET クエリ文字列を操作して、データベース クエリに情報を追加します。たとえば、単純なログイン データベースがあるとします。このデータベースの各レコードには、ユーザー名フィールドとパスワード フィールドがあります。ユーザーがログインできるようにするログイン フォームを作成します。
コードをコピーします コードは次のとおりです:
/title> <div class="codebody" id="code92758"><body> <br>< ;form action= ”verify.php” method=”post”> <br><p><label for='user'>ユーザー名</label> <br><input type='text' name='user' id='user '/> <p><label for='pw'>パスワード</label> <br><input type='password' name='pw' pw'/> <br></p><input type='submit' value='login'/</p> <br></body> ;/html> <br><br> <br> このフォームは、ユーザーが入力したユーザー名とパスワードを受け入れ、ユーザー入力を verify.php というファイルに送信します。このファイルでは、PHP は以下に示すようにログイン フォームからのデータを処理します。 <br><br>リスト 5. 安全でない PHP フォーム処理コード <br><br><br><br> コードをコピー </div> <br> コードは次のとおりです: <br><br> <br><?php <div class="codetitle">$ ok = 0; <span style="CURSOR: pointer" onclick="doCopy('code75005')">$username = $_POST['user']; <U>$pw = $_POST['pw']; </U>$sql = “username=' のユーザーから count(*) を選択します。”ユーザー名 ."' およびパスワード = '"。$pw."' 制限 1"; ctr == 1){ </span>//アプリケーションに入っても大丈夫です! </div>$okay = 1; <div class="codebody" id="code75005">} <BR>if ($okay){ <BR>$_SESSION['loginokay'] = true; Index .php"); <BR>}else{ <BR>header("login.php"); <BR>} <BR>?> <br><br> <br> このコードは問題ありませんね? 世界中の数百 (場合によっては数千) の PHP /MySQL サイトは、このようなコードを使用します。何が問題なのでしょうか? そうですね、「ユーザー入力は信頼できない」ということを思い出してください。ここではユーザーからの情報はエスケープされないため、アプリケーションは脆弱なままになります。具体的には、あらゆる種類の SQL インジェクション攻撃が発生する可能性があります。たとえば、ユーザーがユーザー名として foo を入力し、パスワードとして ' または '1'='1 を入力すると、実際には次の文字列が PHP に渡され、クエリが MySQL に渡されます。以下のように: <br><br> <br><?php <BR>$sql = “select count(*) as ctr from users where username= <BR>'foo' かつpassword=” or '1'='1' limit 1''?> ; <br><br> <br> このクエリは常に 1 のカウントを返すため、ハッカーはパスワード文字列の末尾に悪意のある SQL を挿入することでこの問題を解決できます。これは、組み込みの mysql_real_escape_string() 関数がラッパーとして機能します。この関数は、文字列内の文字をエスケープし、アポストロフィなどの特殊文字を渡すことを不可能にし、それを MySQL で操作できるようにします。コード<br><br>コードは次のとおりです:<br><div class="codebody" id="code21598"> <br><?php <BR>$okay = 0; <BR>$username = $_POST['user']; <BR>$pw = $_POST['pw']; <BR>$sql = "ユーザーから count(*) を選択しますここで、ユーザー名 = '".mysql_real_ <BR>_string($username)."' およびパスワード ='".mysql_real_escape_string($pw)."' <BR>制限 1"; <BR>$result = mysql_query($sql); <BR>while ($data = mysql_fetch_object($result)){ <BR>if ($data->ctr == 1){ // <br>$okay = 1 を入力しても問題ありません! { <br>$_SESSION['loginokay'] = true; <br>header("index.php"); <br>else{ <br>?> mysql_real_escape_string() を使用します。ユーザー入力のラッパーとして、ユーザー入力への悪意のある SQL インジェクションを回避できます。ユーザーが SQL インジェクションを介して不正なパスワードを渡そうとすると、次のクエリがデータベースに渡されます: <br><br><br><br>コードをコピー<br><br> コードは次のとおりです: <br><br> </div>select count(*) as ctr from users whereユーザー名 = 'foo' およびパスワード = <br>'' または '1'='1'' 制限 1'' <br><div class="codetitle"> <span style="CURSOR: pointer" onclick="doCopy('code88486')"> <u></u></span>http://www.bkjia.com/PHPjc/322437.html</div> <div class="codebody" id="code88486">www.bkjia.com<br><br>tru​​e<br> </div>http://www.bkjia.com/PHPjc/322437.html<p align="left">技術記事</p> <div style="display:none;"> <span id="url" itemprop="url"> PHP プログラマー、特に初心者は、インターネットの危険性についてあまりにも知識が乏しいため、外部からの侵入に対して無力であることがよくあります...</span><span id="indexUrl" itemprop="indexUrl"></span><span id="isOriginal" itemprop="isOriginal">。 </span><span id="isBasedOnUrl" itemprop="isBasedOnUrl"></span> </div></div><div class="nphpQianMsg"><div class="clear"></div></div><div class="nphpQianSheng"><span>声明:</span><div>この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。</div></div></div><div class="nphpSytBox"><span>前の記事:<a class="dBlack" title="Jinchengba_PHP チュートリアルによる DiscuzX のフロントエンド最適化の重要なポイント" href="http://m.php.cn/ja/faq/309670.html">Jinchengba_PHP チュートリアルによる DiscuzX のフロントエンド最適化の重要なポイント</a></span><span>次の記事:<a class="dBlack" title="Jinchengba_PHP チュートリアルによる DiscuzX のフロントエンド最適化の重要なポイント" href="http://m.php.cn/ja/faq/309672.html">Jinchengba_PHP チュートリアルによる DiscuzX のフロントエンド最適化の重要なポイント</a></span></div><div class="nphpSytBox2"><div class="nphpZbktTitle"><h2>関連記事</h2><em><a href="http://m.php.cn/ja/article.html" class="bBlack"><i>続きを見る</i><b></b></a></em><div class="clear"></div></div><ul class="nphpXgwzList"><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/2.html" title="正規表現内のすべての式記号 (概要)" class="aBlack">正規表現内のすべての式記号 (概要)</a><div class="clear"></div></li></ul></div></div><div class="nphpFoot"><div class="nphpFootBg"><ul class="nphpFootMenu"><li><a href="http://m.php.cn/ja/"><b class="icon1"></b><p>ホームページ</p></a></li><li><a href="http://m.php.cn/ja/course.html"><b class="icon2"></b><p>コース</p></a></li><li><a href="http://m.php.cn/ja/wenda.html"><b class="icon4"></b><p>に質問</p></a></li><li><a href="http://m.php.cn/ja/login"><b class="icon5"></b><p>私の</p></a></li><div class="clear"></div></ul></div></div><div class="nphpYouBox" style="display: none;"><div class="nphpYouBg"><div class="nphpYouTitle"><span onclick="$('.nphpYouBox').hide()"></span><a href="http://m.php.cn/ja/"></a><div class="clear"></div></div><ul class="nphpYouList"><li><a href="http://m.php.cn/ja/"><b class="icon1"></b><span>ホームページ</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/course.html"><b class="icon2"></b><span>コース</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/article.html"><b class="icon3"></b><span>記事</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/wenda.html"><b class="icon4"></b><span>に質問</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/dic.html"><b class="icon6"></b><span>辞書</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/course/type/99.html"><b class="icon7"></b><span>マニュアル</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/xiazai/"><b class="icon8"></b><span>ダウンロード</span><div class="clear"></div></a></li><li><a href="http://m.php.cn/ja/faq/zt" title="特集"><b class="icon12"></b><span>特集</span><div class="clear"></div></a></li><div class="clear"></div></ul></div></div><div class="nphpDing" style="display: none;"><div class="nphpDinglogo"><a href="http://m.php.cn/ja/"></a></div><div class="nphpNavIn1"><div class="swiper-container nphpNavSwiper1"><div class="swiper-wrapper"><div class="swiper-slide"><a href="http://m.php.cn/ja/" >ホームページ</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/article.html" class="hover">記事</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/wenda.html" >に質問</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/course.html" >コース</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/faq/zt" >特集</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/xiazai" >ダウンロード</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/game" >ゲーム</a></div><div class="swiper-slide"><a href="http://m.php.cn/ja/dic.html" >辞書</a></div><div class="clear"></div></div></div><div class="langadivs" ><a href="javascript:;" class="bg4 bglanguage"></a><div class="langadiv" ><a onclick="javascript:setlang('zh-cn');" class="language course-right-orders chooselan " href="javascript:;"><span>简体中文</span><span>(ZH-CN)</span></a><a onclick="javascript:setlang('en');" class="language course-right-orders chooselan " href="javascript:;"><span>English</span><span>(EN)</span></a><a onclick="javascript:setlang('zh-tw');" class="language course-right-orders chooselan " href="javascript:;"><span>繁体中文</span><span>(ZH-TW)</span></a><a onclick="javascript:;" class="language course-right-orders chooselan chooselanguage" href="javascript:;"><span>日本語</span><span>(JA)</span></a><a onclick="javascript:setlang('ko');" class="language course-right-orders chooselan " href="javascript:;"><span>한국어</span><span>(KO)</span></a><a onclick="javascript:setlang('ms');" class="language course-right-orders chooselan " href="javascript:;"><span>Melayu</span><span>(MS)</span></a><a onclick="javascript:setlang('fr');" class="language course-right-orders chooselan " href="javascript:;"><span>Français</span><span>(FR)</span></a><a onclick="javascript:setlang('de');" class="language course-right-orders chooselan " href="javascript:;"><span>Deutsch</span><span>(DE)</span></a></div></div><script> var swiper = new Swiper('.nphpNavSwiper1', { slidesPerView : 'auto', observer: true,//修改swiper自己或子元素时,自动初始化swiper observeParents: true,//修改swiper的父元素时,自动初始化swiper }); </script></div></div><!--顶部导航 end--><script>isLogin = 0;</script><script type="text/javascript" src="/static/layui/layui.js"></script><script type="text/javascript" src="/static/js/global.js?4.9.47"></script></div><script src="https://vdse.bdstatic.com//search-video.v1.min.js"></script><link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css' type='text/css' media='all'/><script type='text/javascript' src='/static/js/viewer.min.js?1'></script><script type='text/javascript' src='/static/js/jquery-viewer.min.js'></script><script>jQuery.fn.wait = function (func, times, interval) { var _times = times || -1, //100次 _interval = interval || 20, //20毫秒每次 _self = this, _selector = this.selector, //选择器 _iIntervalID; //定时器id if( this.length ){ //如果已经获取到了,就直接执行函数 func && func.call(this); } else { _iIntervalID = setInterval(function() { if(!_times) { //是0就退出 clearInterval(_iIntervalID); } _times <= 0 || _times--; //如果是正数就 -- _self = $(_selector); //再次选择 if( _self.length ) { //判断是否取到 func && func.call(_self); clearInterval(_iIntervalID); } }, _interval); } return this; } $("table.syntaxhighlighter").wait(function() { $('table.syntaxhighlighter').append("<p class='cnblogs_code_footer'><span class='cnblogs_code_footer_icon'></span></p>"); }); $(document).on("click", ".cnblogs_code_footer",function(){ $(this).parents('table.syntaxhighlighter').css('display','inline-table');$(this).hide(); }); $('.nphpQianCont').viewer({navbar:true,title:false,toolbar:false,movable:false,viewed:function(){$('img').click(function(){$('.viewer-close').trigger('click');});}}); </script></body></html>