したいのでサニタイズのユーザー入力とPHP?
-
02-07-2019 - |
質問
はありまcatchall機能のどこかでも通用するための殺菌ユーザー入力のためのSQLインジェクション、クロスサイト-スクリプティング攻撃を可能にする特定の種類のHTMLタグ?
解決
この誤解されるユーザー入力可能です。PHPには、(現在非推奨)"機能"と呼ばれるマジック見積書、ロイヤル-アカデミーのスタイルました。このナンセンスです。をお忘れのフィルタリング(清掃などを呼ぶ人もいます。
にはどうすれば良いか、問題を避けることになるだろう、非常にシンプルです:き埋め込み文字列内の外国コード、避難によると、ルールの言語です。たとえば、埋め込み文字列の一部SQLを対象にMySqlが必要から逃れる文字列のMySqlの機能がこの利用目的mysqli_real_escape_string
).った場合はデータベースを用い、成績はよりよいアプローチが可能)
例えば、HTML:組み込めば文字列内のHTMLマークアップが必要脱出で htmlspecialchars
.この一 echo
または print
書の利用 htmlspecialchars
.
第三の例できるシェルコマンド:る場合には埋め込み文字列などの引数を外部コマンドを呼び出し exec
, その使用 escapeshellcmd
や escapeshellarg
.
などなど...
の のみ 場合に必要なものを積極的にデータをフィルターであれば受付書式設定済みの入力です。例えば.ができるようになってしまいますユーザーの投稿HTMLマークアップ、プラン表示のサイトです。しかし、賢明なこれを避けるためにすべてのコストで、いかにもフィルターでであることに潜在的なセキュリティホール。
他のヒント
ならないように気をつけましょうSQLインジェクションによる殺菌の入力データです。
代わりに、 なく使用するデータを作成するSQLコード.成功した場合(パラメータを用いてテンプレートクエリ)を使用する行きの変数.この保証対SQLインジェクション
ご自由にお使いくださいwebサイト http://bobby-tables.com/ についての防止にSQLインジェクション
No.できない属フィルターなしのデータを任意のコンテキストのようです。時にはまた、SQLクエリーを入力として、時にはまたはHTMLとして入力します。
必要なものをフィルタの入力にwhitelist--確実にデータをマッチの仕様のますが、ご了承ください。する必要があり脱出する前にできるので、によってはコンテキストを使用します。
を抜け出しデータ形式のいずれか)で挿入するに当たってのSQLインジェクションは非常に異なるから抜け出しデータ(X)HTMLを防ぐため、クロスサイト-スクリプティング.
PHPの新しい素敵なfilter_input機能は現在、インスタンスを解放し、だから求究極のe-mail regex"今があることを内蔵FILTER_VALIDATE_EMAILタイプ
自分のフィルタークラスでは、javascriptを使用してイ故障分野)によって開始されるいずれかをajaxでの請求または通常形態。(以下の例)
/**
* Pork.FormValidator
* Validates arrays or properties by setting up simple arrays.
* Note that some of the regexes are for dutch input!
* Example:
*
* $validations = array('name' => 'anything','email' => 'email','alias' => 'anything','pwd'=>'anything','gsm' => 'phone','birthdate' => 'date');
* $required = array('name', 'email', 'alias', 'pwd');
* $sanatize = array('alias');
*
* $validator = new FormValidator($validations, $required, $sanatize);
*
* if($validator->validate($_POST))
* {
* $_POST = $validator->sanatize($_POST);
* // now do your saving, $_POST has been sanatized.
* die($validator->getScript()."<script type='text/javascript'>alert('saved changes');</script>");
* }
* else
* {
* die($validator->getScript());
* }
*
* To validate just one element:
* $validated = new FormValidator()->validate('blah@bla.', 'email');
*
* To sanatize just one element:
* $sanatized = new FormValidator()->sanatize('<b>blah</b>', 'string');
*
* @package pork
* @author SchizoDuckie
* @copyright SchizoDuckie 2008
* @version 1.0
* @access public
*/
class FormValidator
{
public static $regexes = Array(
'date' => "^[0-9]{1,2}[-/][0-9]{1,2}[-/][0-9]{4}\$",
'amount' => "^[-]?[0-9]+\$",
'number' => "^[-]?[0-9,]+\$",
'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$",
'not_empty' => "[a-z0-9A-Z]+",
'words' => "^[A-Za-z]+[A-Za-z \\s]*\$",
'phone' => "^[0-9]{10,11}\$",
'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$",
'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$",
'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$",
'2digitopt' => "^\d+(\,\d{2})?\$",
'2digitforce' => "^\d+\,\d\d\$",
'anything' => "^[\d\D]{1,}\$"
);
private $validations, $sanatations, $mandatories, $errors, $corrects, $fields;
public function __construct($validations=array(), $mandatories = array(), $sanatations = array())
{
$this->validations = $validations;
$this->sanatations = $sanatations;
$this->mandatories = $mandatories;
$this->errors = array();
$this->corrects = array();
}
/**
* Validates an array of items (if needed) and returns true or false
*
*/
public function validate($items)
{
$this->fields = $items;
$havefailures = false;
foreach($items as $key=>$val)
{
if((strlen($val) == 0 || array_search($key, $this->validations) === false) && array_search($key, $this->mandatories) === false)
{
$this->corrects[] = $key;
continue;
}
$result = self::validateItem($val, $this->validations[$key]);
if($result === false) {
$havefailures = true;
$this->addError($key, $this->validations[$key]);
}
else
{
$this->corrects[] = $key;
}
}
return(!$havefailures);
}
/**
*
* Adds unvalidated class to thos elements that are not validated. Removes them from classes that are.
*/
public function getScript() {
if(!empty($this->errors))
{
$errors = array();
foreach($this->errors as $key=>$val) { $errors[] = "'INPUT[name={$key}]'"; }
$output = '$$('.implode(',', $errors).').addClass("unvalidated");';
$output .= "new FormValidator().showMessage();";
}
if(!empty($this->corrects))
{
$corrects = array();
foreach($this->corrects as $key) { $corrects[] = "'INPUT[name={$key}]'"; }
$output .= '$$('.implode(',', $corrects).').removeClass("unvalidated");';
}
$output = "<script type='text/javascript'>{$output} </script>";
return($output);
}
/**
*
* Sanatizes an array of items according to the $this->sanatations
* sanatations will be standard of type string, but can also be specified.
* For ease of use, this syntax is accepted:
* $sanatations = array('fieldname', 'otherfieldname'=>'float');
*/
public function sanatize($items)
{
foreach($items as $key=>$val)
{
if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue;
$items[$key] = self::sanatizeItem($val, $this->validations[$key]);
}
return($items);
}
/**
*
* Adds an error to the errors array.
*/
private function addError($field, $type='string')
{
$this->errors[$field] = $type;
}
/**
*
* Sanatize a single var according to $type.
* Allows for static calling to allow simple sanatization
*/
public static function sanatizeItem($var, $type)
{
$flags = NULL;
switch($type)
{
case 'url':
$filter = FILTER_SANITIZE_URL;
break;
case 'int':
$filter = FILTER_SANITIZE_NUMBER_INT;
break;
case 'float':
$filter = FILTER_SANITIZE_NUMBER_FLOAT;
$flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND;
break;
case 'email':
$var = substr($var, 0, 254);
$filter = FILTER_SANITIZE_EMAIL;
break;
case 'string':
default:
$filter = FILTER_SANITIZE_STRING;
$flags = FILTER_FLAG_NO_ENCODE_QUOTES;
break;
}
$output = filter_var($var, $filter, $flags);
return($output);
}
/**
*
* Validates a single var according to $type.
* Allows for static calling to allow simple validation.
*
*/
public static function validateItem($var, $type)
{
if(array_key_exists($type, self::$regexes))
{
$returnval = filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false;
return($returnval);
}
$filter = false;
switch($type)
{
case 'email':
$var = substr($var, 0, 254);
$filter = FILTER_VALIDATE_EMAIL;
break;
case 'int':
$filter = FILTER_VALIDATE_INT;
break;
case 'boolean':
$filter = FILTER_VALIDATE_BOOLEAN;
break;
case 'ip':
$filter = FILTER_VALIDATE_IP;
break;
case 'url':
$filter = FILTER_VALIDATE_URL;
break;
}
return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false;
}
}
もちろん、意が必要なsqlクエリも逃げによってどのようなdbのご利用(mysql_real_escape_string()は無用のための、sql serverのためのインスタンス).だいたい対応で、自動的に適したアプリケーションレイヤのようにORM.また、上述のように:出力するhtmlをご利用その他のphp専用の機能htmlspecialchars;)
も可能なHTMLの入力のように剥クラスまたはタグに依存し、専用のクロスサイト-スクリプティングの検証パッケージ。なおREGEXESの解析をHTML!
いいえ、ございません。
まず、SQLインジェクションの入力フィルタリングの問題は、クロスサイト-スクリプティングが出力エスケープについなものを実行しこれら二つの作業と同時に、コードのライフサイクルになっています。
基本的なルールの親指
- SQLクエリー結合するパラメータとしてPDOを使うドライバー-ネイティブの脱出機能はクエリの変数など
mysql_real_escape_string()
) - 使用
strip_tags()
フィルターの出は不要なHTML - 逃がすべてのその他の出力
htmlspecialchars()
とに留意すること、第2、第3のパラメータです。
ワトリックするので、特定の状況がすようなページ /mypage?id=53
ご使用のidをWHERE節するためのid詳細情報が整数のように:
if (isset($_GET['id'])) {
$id = $_GET['id'];
settype($id, 'integer');
$result = mysql_query("SELECT * FROM mytable WHERE id = '$id'");
# now use the result
}
ものだけをカットし、特定の攻撃、その他の応答となります。(およびそのきっかけをつくっていきたことを知らない上記コードな素晴らしいですけど、この特定の皆様をお迎えします。)
法殺菌ユーザの入力をリリースでは以下のセキュリティ:
利用の現代バージョンのMySQLとPHP.
セットの文字セットを明示的に:
$mysqli->set_charset("utf8");
マニュアル$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);
マニュアル$pdo->exec("set names utf8");
マニュアル$pdo = new PDO( "mysql:host=$host;dbname=$db", $user, $pass, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ) );
マニュアル
[推奨されていませんPHP5.5.0除去したり、PHP7.0.0から].mysql_set_charset('utf8')
セキュリティを使用の文字セット:
- 選択utf8,latin1、ascii..ゴの使用に脆弱な文字セットbig5、cp932,gb2312,gbk、sjis.
利用spatialized機能:
- MySQLiの作諸表の作成に
$stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$param = "' OR 1=1 /*";
$stmt->bind_param('s', $param);
$stmt->execute(); PDO::quote() -場所な引用符を文字列の入力(必要な場合)、およびそのエスケープの特殊文字以内の文字列の入力を引用スタイルの適切な基本となるドライバ:
$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);明示的にセットの文字セット
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);無効化模倣した諸表作成の防止スクフォースメンバーである模擬算MySQLできな準備ネイティブのを避けるために射出)
$var = $pdo->quote("' OR 1=1 /*");なエスケープのリテラルにも引用符で単一引用符'文字以内) $stmt = $pdo->query("SELECT * FROM test WHERE name = $var LIMIT 1");PDO諸表の作成:vs MySQLi諸表作成の支援データベースのドライバーや名前のパラメータ:
$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);明示的にセットの文字セット
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);無効化模倣した諸表作成の防止スクフォースメンバーである模擬算MySQLできな準備ネイティブのを避けるために射出) $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(["' OR 1=1 /*"]);mysql_real_escape_string[推奨されていませんPHP5.5.0除去したり、PHP7.0.0から].- mysqli_real_escape_string エスケープ特殊文字は文字列で使用SQLステートメントを踏まえ、現在の文字セットに接続します。がおすすめ成功した場合でないという理由によって、単に逃れた文字列を書が出てくる完全なクエリの実行計画を含めるテーブルと指標うな方法で壁紙を回転できることでは最適化されます。
- 使用単一引用符('')周辺の変数内にお返します。
- MySQLiの作諸表の作成に
チェックの変数を含んだ期待した:
- ご期待整数を使用します:
ctype_digit — Check for numeric character(s);
$value = (int) $value;
$value = intval($value);
$var = filter_var('0755', FILTER_VALIDATE_INT, $options); - 文字列の使用
is_string() — Find whether the type of a variable is string
使用 フィルター機能 filter_var()—フィル変数指定されたフィルタ:$email = filter_var($email, FILTER_SANITIZE_EMAIL);
より所定のフィル
$newstr = filter_var($str, FILTER_SANITIZE_STRING); - filter_input() —が特定の外部変数の名前およびオプションでフィード:
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
- preg_match() —を行う正規表現に一致;
- 書き独自の検証機能です。
- ご期待整数を使用します:
うに記述するここでは二つの別々の課題
- サニタイズ/フィルタリングのユーザ入力データです。
- 逃げ出力に出力します。
1)ユーザの入力を常に想定されます。
利用成功した場合、または/およびフィルタリングとmysql_real_escape_stringは必須となります。PHPもfilter_input築するのに良い場所です。
2)この大きな課題でのコンテキストのデータが出力されます。HTMLあるなどのソリューションhtmlpurifierがあります。経験則として、常に脱出するための出力に出力します。
両方の問題はあまりにも大きく単一のポストがあり、多くの投稿はさらに詳細:
使用している場合は、PostgreSQL、入力からPHPでき覧pg_escape_string()
$username = pg_escape_string($_POST['username']);
からのドキュメント(http://php.net/manual/es/function.pg-escape-string.php):
pg_escape_string()エスケープ文字列のために照会データベースです。を返します逃れた文字列は、PostgreSQLの形式になります
最も簡単な方法ミスを回避するために殺菌力、脱出データのPHPを利用した枠組みのように Symfony, Nette など。またはその枠組み(孔のエンジン、データベース層のORM).
孔のエンジンのように 小枝 ョンが出力エスケープによるデフォルト-のあいだに解決手動の場合適切にエスケープされた出力によってはコンテキスト(HTMLやJavascript部分のウェブページ上)。
枠組みは自動的に殺菌力すべき使用しな$_POST,$_GETや$_SESSION変数を直接のですが、機構のようなルーティング、セッションの取扱い等
およびデータベース(プラモデル)層がORMの枠組みのような理念や包装の周辺PDOのようにNetteデータベースです。
につなげていくかを学びますので、ここに- うソフトウェアさせていただきます。
ありませんcatchall機能が複数の懸念しなければならない。
SQLインジェクション -現在、一般的には、PHPのプロジェクトを使用 成績通PHPのデータオブジェクト(PDO) としてのベストプラクティス、 防止にエラーからの迷を引用などの表示液を防注射.でも最もフレキシブル&安心へアクセスデータベースです。
チェック (の)PDOチュートリアル たかくんだ、クリエイティブオフィスで約PDO.(誠実さトップでの執筆、@YourCommonSense、この偉大な資源になれます。)
クロスサイト-スクリプティング-サニタイズのデータの...
HTML清浄機 いているのに長い時間が積極的に更新されます。使用できるサニタイズする悪意のある入力を可能にする豊かな。whitelistのタグです。本作は多くのWYSIWYGエディタですが船舶海洋工学の分野においては一部の利用例です。
その他のインスタンスがいいなHTML/Javascriptでは、がその場で発音を確認することがこの単純な機能を利用しなが渡された複数の監査クロスサイト-スクリプティング):
/* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
クロスサイト-スクリプティング-サニタイズのデータを出--- いない場合の保証のデータを適切に消毒することができるサプリのデータベースする必要がありまサニタイズして表示するまでにユーザーまでのレバレッジのこれらの有PHP関数:
- をご利用いただきます
echo
またはprint
表示ユーザによって提供された値を使用htmlspecialchars
ない限り、データは適切な消毒安全では表示が許可されたHTML. json_encode
より安全な方法をユーザによって提供された値からPHPト
- をご利用いただきます
なお電話の外部シェルコマンドを使用
exec()
またはsystem()
機能またはbacktick
オペレーター? その場合、SQLインジェクション&クロスサイト-スクリプティングといった追加を懸念するため、 ユーザー走悪意のあるコマンドはサーバ.を使用する必要がありescapeshellcmd
だから逃れるコマンド全体またはescapeshellarg
脱個別の引数です。
い信頼ユーザーデータです。
function clean_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
の trim()
関数を削除しの空白文字およびその他の定義済みの文字の両面からの文字列になります。
の stripslashes()
関数を削除しバックスラッシュ
の htmlspecialchars()
機能変換の一部定義済みの文字のHTMLる。
所定の文字:
& (ampersand) becomes &
" (double quote) becomes "
' (single quote) becomes '
< (less than) becomes <
> (greater than) becomes >
<url> <url> <url> <url> <url> <url> <url> <url> <url> <url>を追加するのが出力エスケープを使いたい場合、php DOMDocumentおhtml出力を自動的にスケープの右コンテキスト属性(value="")をテキストの <span> ない平等なものとする。安全クロスサイト-スクリプティングに対す:OWASP防止クロスサイト-スクリプティングチートシート
すなサニタイズ入力します。
常にサニタイズを出力します。
の変換に適用するデータでの安全等が含まれている場合はSQLステートメントとはまったく異なった使用等が含まれている場合はHTMLとはまったく異なった使用等が含まれている場合はJavascriptとはまったく異なった使用等が含まれている場合はLDIFとはまったく異なった申し込み含CSSとはまったく異なった使用を含むメール....
ぜひ 検証の入力 -かばせて頂いた上で受付させて頂きるように加工を教えてあげたり、ユーザーで放置するわけにはいきません。なかった場合、変更に表現までの間、データのいPHP。
昔の人た発明のニーズ全機構の脱出データでしまいましたが"magic_quotes"がんを適切に逃がすデータのためのすべての出力の目標と結果、異なったインスタレーションを必要と異なるコードです。
きphpフィルタのサニタイズ特別な特殊文字は重宝しています。
のように:
$a=fliter_var($_POST['a'],FILTER_SANITIZE_SPECIAL_CHARS);
しかし、在庫されてはいかがでしょうか、より良いためのcコードでフィルの"'\ < >&る0だったのでこすると良い意味での抗菌なしかし、これだけのソースコードを含むその他のキャラクターのように/{}[].;`強化のためこの機能のエンコード(enc["]):
void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
{
unsigned char enc[256] = {0};
php_filter_strip(value, flags);
/* encodes ' " < > & \0 to numerical entities */
enc['\''] = enc['"'] = enc['<'] = enc['>'] = enc['&'] = enc[0] = 1;
/* if strip low is not set, then we encode them as &#xx; */
memset(enc, 1, 32);
if (flags & FILTER_FLAG_ENCODE_HIGH) {
memset(enc + 127, 1, sizeof(enc) - 127);
}
php_filter_encode_html(value, enc);
}
最も基本的な方法殺菌ユーザの入力をリリースでは以下のセキュリティ:
function sanitizeString($var)
{
$var = stripslashes($var);
$var = strip_tags($var);
$var = htmlentities($var);
return $var;
}
function sanitizeMySQL($connection, $var)
{
$var = $connection->real_escape_string($var);
$var = sanitizeString($var);
return $var;
}