2009-07-08 14 views
0

私は出発地と目的地のアドレスを入力し、ルートを示す地図とともに道順表(道順情報を与える)を取得する道順サービスに取り組んでいます。あなたはそれがgetdirections.phpとしてシステム名にこのコードを試してみる場合はユーザ入力、PHP、Javascript、セキュリティ

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 
<title>Directions</title> 
<style> 
    * { font-family: Verdana; font-size: 96%; } 
    label { width: 15em; float: left; } 
    label.error { display: block; float: none; color: red; vertical-align: top; } 
    p { clear: both; } 
    .submit { margin-left: 12em; } 
    em { font-weight: bold; padding-right: 1em; vertical-align: top; } 
</style> 
<script src="jquery-1.3.1.js" type="text/javascript"> 
</script> 
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false& amp;key=[Your Key Here]" 
type="text/javascript"> 
</script> 
</head> 
<body onunload="GUnload()"> 
<div id="container">  
<div id="directform"> 
    <form id="direct" action="getdirections.php" method="get"> 
<p><label for="loc1">From Here:</label> 
<input id="loc1" type="text" name="location1" class="required" /></p> 
<p><label for="loc2">To Here:</label> 
<input id="loc2" type="text" name="location2" class="required" /></p> 
<p><input type="submit" value="Search" /></p> 
    </form> 
</div> 
<?php 
function filterInput ($input) { 
$replacement = ','; 
$input = preg_replace('/(\n|\r)+/', $replacement, $input); 
$replacement = " "; 
$input = preg_replace('/(\t)+/', $replacement, $input); 
$inputarray = explode(' ', $input); 
foreach ($inputarray as $i => $value) { 
    $ch = ''; 
    if ($value[strlen($value)-1] == ',') { 
    $ch = ','; 
    $value = substr($value, 0, -1); 
    } 

$value = 
     preg_replace('/^(\&|\(|\)|\[|\]|\{|\}|\"|\.|\!|\?|\'|\:|\;)+/', "", $value); 

$inputarray[$i] = 
     preg_replace('/(\&|\(|\)|\[|\]|\{|\}|\"|\.|\!|\?|\'|\:|\;)+$/', "", $value); 
$inputarray[$i] = $inputarray[$i].$ch; 
} 
$filteredString = implode(" ", $inputarray); 
return $filteredString; 
} 

?> 
</div>  
<table class="directions"> 
<tr> 
<td valign="top"> 
    <div id="directions" style="width: 100%"></div> 
</td> 
</tr> 
<tr> 
<td valign="top"> 
<div id="map_canvas" style="width: 250px; height: 400px"></div> 
</td> 
</tr> 
<td valign="top"> 
<div id="directions_url"></div> 
</td> 
</table> 

<noscript><b>JavaScript must be enabled in order for you to use Google Maps.</b> 
    However, it seems JavaScript is either disabled or not supported by your browser. 
    To view Google Maps, enable JavaScript by changing your browser options, and then 
    try again. 
</noscript> 
<script type="text/javascript"> 

// This programming pattern limits the number of global variables 
// Thus it does not pollute the global namespace 
// for_directions is the only global object here. 
for_directions = function(){ 

// The map is loaded into the div element having id specified by mapid 
// private variable 
var mapid = "map_canvas"; 

// The direction listing is loaded into the div element having id specified by directionsid. 
// private variable 
var directionsid = "directions"; 

// From here 
// private variable 
var location1; 

// To here 
// private variable 
var location2; 

// The functions (init and addevent) are public methods of for_directions object 
return { 
    // Called on loading of this page 
    // public method 
    init: function(){ 
     location1 = "<?= filterInput($_GET['location1']) ?>" || 0; 
     location2 = "<?= filterInput($_GET['location2']) ?>" || 0; 
     var directions = document.getElementById(directionsid); 
     directions.innerHTML = "Please check the address and try again"; 

     if (GBrowserIsCompatible() && location1 != 0 && location2 != 0){ 
      mapAddress(location1, location2); 
      } 
    }, 

    // This method is cross browser compliant and is used to add an event listener 
    // public method 
    addEvent:function(elm,evType,fn,useCapture){ 
     if(elm.addEventListener){ 
      elm.addEventListener(evType, fn, useCapture); 
      return true; 
     } else if (elm.attachEvent) { 
      var r = elm.attachEvent('on' + evType, fn); 
      return r; 
     } else { 
      elm['on' + evType] = fn; 
     } 
    } 
}; 

// Called from init 
// private method 
    function mapAddress (address1, address2){ 
     var geocoder = new GClientGeocoder(); 
    var directions = document.getElementById(directionsid); 
    var i = 0; 

    geocoder.getLatLng(address1, function(point1){ 
     if (point1){ 
     geocoder.getLatLng (address2, function(point2){ 
      if (point2){ 
      getDirections(); 
      } else { 
      directions.innerHTML = "Please check the address and try again"; 
      } 

     }); 
     } else { 
     directions.innerHTML = "Please check the address and try again"; 
     } 

    }); 
} 

// Called from mapAddress to load the directions and map 
// private method 
function getDirections(){ 
    var gmap = new GMap2(document.getElementById(mapid)); 
    var gdir = new GDirections(gmap,document.getElementById(directionsid)); 
    gdir.load("from: " + location1 + " to: " + location2, 
      { "locale": "en_US" }); 
    generateURL(); 
} 

function generateURL(){ 
    var url = "http://maps.google.com/maps?saddr="; 
    url += location1; 
    url += "&daddr="; 
    url += location2; 
    var a = $("<a></a>").attr('href',url); 
    $(a).text("Google Maps"); 
    $("#directions_url").append(a); 
} 
}(); 
// The(); above results in the function being interpreted by the browser just before the page is loaded. 

// Make for_directions.init as the listener to load event 
// Note that the init method is public that why its accessible outside the object scope 
for_directions.addEvent(window, 'load', for_directions.init, false); 
</script> 
</body> 
</html> 

:以下

は、完全なソースコード(getdirections.php)です。あなたが変更する必要がある唯一のものは、Googleマップのapiキーです。キーhereを得ることができます。

あなたがkeyパラメータに入れて、あなたの鍵を生成した後は、(便宜上、以下の行を再現):

<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false& amp;key=[Your key here]" 
type="text/javascript"> 

を上記のコードから分かるように、私はPHPを介して入力を取得し、JavaScriptで処理を行います。今、私はユーザーがどんな種類の入力(javscript、危険なHTMLなど)で逃げるのを望んでいません。私はPHPでurlencode関数を使ってみました。ただし、コード化されたユーザー入力はJavaScriptコードでは受け入れられず、入力が良好であっても失敗します。

私はこの問題を回避するために、特定の文字を置き換えたり削除したりするためにPHPでfilterInput関数を書いています。ユーザーが入力を介してJavaScriptコードを試して実行しようとする試みを阻止します。

これはうまくいきました。しかし、ユーザーが悪意のある入力をした場合、たとえば "+ alert(" hello ")+"のように開始と終了の両方の引用符を含めると、filterInput関数は先頭と末尾の引用符をトリミングし、結果の文字列は以下のようになります。

+alert("hello")+ 

以下のコードが実行される:Sの

location1 = "+alert("hello")+" || 0; 

実行:

location1 = "<?= filterInput($_GET['location1']) ?>" || 0; 

PHPは、以下のようにその戻り値を持つ関数呼び出しをsubstitues criptは上の行でエラーで停止します(欠落しています。前のステートメント)

注:私は引用符をトリムしていないし、$ _GET ['location1']を直接使用しました。

location1 = ""+alert("hello")+"" || 0; 

alert( "hello")が実行されます。

ですから、私は修正を受けています。私は入力をフィルタリングする場合、私は特定のユーザー入力でJavaScriptエラーを取得し、私は入力をフィルタリングしない場合は、ユーザーが任意の種類のJavaScriptを実行することができます。

私の質問は、以下のとおりです。

  • ウェブ上で入力を処理するために、適切かつ安全な方法は何ですか?
  • この種のユーザー入力クロス(PHPからJavascriptへ)の言語はOKですか?
  • javascriptを実行できるユーザー以外に、この脆弱なコードは他の種類のセキュリティ上の脅威が何ですか?

お読みください!

助けてください。

+1

なぜ、自分のセッションで任意のJSを実行しているユーザーが心配ですか?とにかくFirebugなどでそれらを行うことができます。通常の攻撃経路には、サーバー側のプロセス(PHPやデータベースサービスを含む)や他のユーザーのセッション(XSS攻撃を含む)への攻撃が含まれます。人々が自分のブラウザを混乱させたい場合、なぜそれらを止めようとしますか?実際、この場合はサーバー側の処理が本当に必要なのですが、init関数をonClickハンドラとして実行し、JSでフォーム値を取得するだけで済みます。 – steamer25

答えて

1

json_encodeはPHPで、評価はjavascriptで試すことができます。

JSが入力が行われたマシンと同じマシンで実行される場合、私はセキュリティについてあまり心配しません。ハッカーは自分のマシンをハックすることができますが、それは問題ではありません。