最も一般的なWebアプリケーションのセキュリティの弱点は、クライアントまたは環境からの入力を適切に検証できないことです。
OWASP、データ検証(2017年7月2日)
信頼できない入力を適切に処理できないと、クロスサイトスクリプト(XSS)などのコードインジェクション攻撃に対して脆弱なアプリケーションが残ります。 「クライアントまたは信頼されていないソースからの入力に対する何らかの形の目に見える汚染」は、depth延の戦略の一環として、OWASPが推奨する1つの対策です。
このPythonモジュールは、特別なタイプにラッピングすることにより、信頼できない入力を「汚染」します。これらのタイプは、ネイティブのPythonタイプと同じようにほとんどの点で動作しますが、誤って価値を使用することを妨げます。これは、「目に見えるタインティング」だけでなく、ランタイム保証、および(オプションで)静的に検証可能なタイプの安全性をMyPyで提供します。
入力を消毒、脱出、正規化、または検証するための戦略は、このモジュールの範囲外です。
このモジュールは、次の警告を使用して、生産の使用に適している必要があります。
untrusted.sequenceタイプにはテストが欠落しており、不完全な場合がありますuntrusted.mappingタイプにはテストが欠落しており、不完全な場合がありますunstrusted.<*>Of完全にテストされていませんセキュリティ上の考慮事項を備えたコードは、精査の最高水準に値します。このモジュールを使用する前に、判断を下してください。
ソフトウェアは、いかなる種類の保証もなく、「現状のまま」提供されます。
Python> = 3.4でテストされていますが、以前のバージョンが機能する場合があります。
sudo pip3 install untrusted --upgrade
(Python3のみをインストールしている場合は、 pipのみが必要になる場合がありますpip3ではなく)
import html # for html.escape
import untrusted
line = untrusted . string ( input ( "Enter some text, HTML will be escaped: " ))
try :
# You're not allowed to print an untrusted.string!
# This raises a TypeError!
print ( "<b>You typed:</b> " + line )
except TypeError :
pass # Expected
# Safely escape the HTML!
print ( "<b>You typed:</b> " + line / html . escape )
# / is overloaded as shorthand for:
# print("<b>You typed:</b> " + line.escape(html.escape)) untrusted.stringストリングタイプstrタイプのように見えますが、逃げずに出力することはできませんstrタイプとシームレスに相互運用可能strの混合使用とuntrusted.string汚染str値/ untrusted.stringタイプにそれらを促進します。信頼されていないHTMLを処理する例:
import html # for html.escape()
import untrusted
# example of a string that could be provided by an untrusted user
firstName = untrusted . string ( "Grace" )
lastName = untrusted . string ( "<script>alert('hack attempt!');</script>" )
# works seamlessly with native python strings
fullName = firstName + " " + lastName
# fullName was tainted and keeps the untrusted.string type
print ( repr ( fullName )) # <untrusted.string of length 46>
# the normal string methods still work as you would expect
fullName = fullName . title ()
# but you can't accidentally use it where a `str` is expected
try :
print ( fullName ) # raises TypeError - untrusted.string used as a `str`!
fullName . encode ( 'utf8' ) # also raises TypeError
except TypeError :
print ( "We caught an error, as expected!" )
# instead, you are forced to explicitly escape your string somehow
print ( "<b>Escaped output:</b> " + fullName . escape ( html . escape )) # prints safe HTML!
print ( "<b>Escaped output:</b> " + fullName / html . escape ) # use this easy shorthand!複数のエスケープ関数を作成し、関数をエスケープするために引数を渡すなどについては、 untrustedStringExample.py参照してください。
このモジュールは、信頼できない値のコレクションを怠lapに包むタイプを提供します。値は、適切なuntrusted.*アクセス時のタイプで包まれています。
untrusted.iteratoruntrusted.*タイプによってラップされた値のみが生成されますuntrusted.string例:
import html # for html.escape
import untrusted
it = untrusted . iterator ( open ( "example.txt" ))
for i , s in enumerate ( it ):
print ( "Line %d: %s" % ( i , s . escape ( html . escape ). strip ())) examples/untrustedIteratorExample.pyを参照してください(例: untrusted.string untrusted.iterator untrusted.iterator
untrusted.sequencelistのリストのようなビューです。untrusted.*タイプによってラップされますuntrusted.string例:
import html # for html.escape
import untrusted
# list of strings from an untrusted source
animals = [ "cat" , "dog" , "monkey" , "elephant" , "<big>mouse</big>" ]
untrustedAnimalList = untrusted . sequence ( animals )
assert "cat" in untrustedAnimalList untrusted.mappingdictのようなオブジェクトのようなビューです。untrusted.*タイプによって包まれています。str > untrusted.stringですが、マッピングはunstrusted.string > untrusted.string 、または信頼できないコレクションへのマッピングである可能性があります。例:
import html # for html.escape
import untrusted
user = untrusted . mapping ({
'username' : 'example-username<b>hack attempt</b>' ,
'password' : 'example-password' ,
})
try :
print ( user . get ( "username" ))
except TypeError :
print ( "Caught the error we expected!" )
print ( user . get ( "username" , "default-username" ) / html . escape )例:
import html # for html.escape
import untrusted
untrustedType = untrusted . mappingOf ( untrusted . string , untrusted . string )
args = untrustedType ({ 'animal' : 'cat' , '<b>hack</b>' : 'attempt' })
for k , v in args . items ():
print ( "%s: %s" % ( k / html . escape , v / html . escape ))ゆっくりとネストされた容器も完全にサポートされています。
untrusted.iteratorOf(valueType) 、 untrusted.sequenceOf(valueType) 、またはuntrusted.mappingOf(keyType, valueType)を使用して、特定のコンテナタイプを作成します。
例:
import html # for html.escape
import untrusted
people = [
{
'id' : 'A101' ,
'name.first' : 'Grace' ,
'name.last' : 'Hopper' ,
'name.other' : 'Brewster Murray' ,
'dob' : '1906-12-09' ,
},
{
'id' : 'A102' ,
'name.first' : 'Alan' ,
'name.last' : 'Turing' ,
'name.other' : 'Mathison' ,
'dob' : '1912-06-23' ,
},
{
'id' : 'HACKER' ,
'name.first' : 'Robert ' ); DROP TABLE Students;--' ,
'name.last' : '£Hacker' ,
'dob' : '<b>Potato</b>'
},
]
# a list of dicts with trusted keys, but untrusted values
mappingType = untrusted . sequenceOf ( untrusted . mapping )
# aka (setting defaults explicitly)
mappingType = untrusted . sequenceOf ( untrusted . mappingOf ( str , untrusted . string ))
for person in mappingType ( people ):
for key , value in person . items ():
print ( " %s: %s" % ( key , value . escape ( html . escape )))ほとんどのネイティブstrメソッドをサポートしますが、リターンタイプが異なる場合があります。
根本的な価値 - 常にstrの非非インスタンス。
untrusted.string(s)
untrusted.stringオブジェクトを構築します。ここで、 s strまたはuntrusted.stringできない。ストリングの非非インスタンスです。
untrusted.stringストリングが信頼されてuntrusted.string 。 strを逃がすと、 untrusted.stringていない。
untrusted.string.escape(escape_function, [*args, **kwargs]) -> str
Optional引数とキーワード引数を使用して、 escape_function str -> strします。
untrusted.string.valid(valid_function, [*args, **kwargs]) -> bool
Optional引数とキーワード引数を使用して、文字列をチェックしてtrueまたはfalsを返す関数str -> boolあるvalid_function適用します。
untrusted.string.valid(validate_function, [*args, **kwargs]) -> any
Optional引数とキーワード引数を使用して、 valid_function 、 str -> anyを適用します(たとえば、文字列が検証されなかった理由のリスト)。
untrusted.string / escape_exprいくつかの脱出表現の場合、 untrusted.string("value") / escape_expr -> str
ここのescape_expr 、文字列を逃れる関数str -> strまたは3 -tuple (escape_function, args, kwargs_dict)のいずれかです。
import html # for html.escape
import untrusted
myString = untrusted . string ( "<b>Exam " ple</b>" )
myEscape = ( html . escape , [], { 'quote' : False })
print ( myString / html . escape )
print ( myString / myEscape ) collectionは、 iteratorの1つ、 sequence (リストのような)、 mapping (dict-like)、またはユーザー構築されたカスタムタイプです。
ほとんどのネイティブコレクション方法をサポートしていますが、リターンタイプが異なる場合があります。
各コレクションは、その値の種類を認識しています(デフォルトのuntrusted.string )。
マッピングはキータイプ(デフォルトstr )も認識しています
基礎となる値 - 常にコレクションの値タイプのインスタンスである非非オブジェクト。
untrusted.iteratorOf(type)を使用してイテレータータイプを作成します。
untrusted.sequenceOf(type)を使用してシーケンスタイプを作成します。
untrusted.sequenceOf(keyType, valueType)を使用してマッピングタイプを作成します。
これらの定義は再帰的です。
例えば:
import untrusted
itType = untrusted . iteratorOf ( untrusted . iteratorOf ( untrusted . string ))
seqType = untrusted . sequenceOf ( itType )
mappingType = untrusted . mappingOf ( untrusted . string , seqType )
someDict = {}
myMapping = mappingType ( someDict )
# or, as a less readable one-liner
myMapping = untrusted . mappingOf ( untrusted . string , seqType )( someDict )1つの方法を使用してuntrusted.stringことを逃れるために、 strへのストリングを使用したからといって、他のコンテキストでは安全ではないかもしれません。たとえば、HTMLにとって安全なものは依然として危険なSQLである可能性があります。ユーザーの入力がキャプチャされたとき、それが使用されるべきコンテキストが事前に知られていない場合があります - したがって、正しい検証と逃亡戦略は何であるかはまだわからない。最終的な使用ポイントまで脱出を遅らせることが最善です - 値untrusted.*可能な限り長く。
このモジュールは魔法のソリューションではありません。賢明に使用するツールです。 「今はstrなので、完全に安全だ」という価値について考えるというtrapに陥らないでください。
文字列を安全に逃れることができるからといって、許容入力として検証されたという意味ではありません。たとえば、パスワードに最小制限を設ける場合があります。または、入力が予約されたファイル名ではないことを要求する場合があります。
これを行うための素晴らしい方法は、 unstruted.string.validメソッドを使用することです。これは、ブールValueError 、信頼できないuntrusted.string.validateメソッドを返します。
時々、あなたは自分でHTMLを生成し、逃げることはあなたがする必要があることです。
インターフェイスは、ほとんどの最新のSQLライブラリのように、常にパラメーターをコードから分離する場合があります。この場合、データベースドライバーは、あなたがこれまでに望んでいたよりも優れた潜在的に信頼されていない入力を処理し、それを逃れることは間違ったことです。
他の理由で信頼されていないものとして入力をマークする場合があります - たとえば、検索クエリで最大長を実施するか、ビジネスロジックに対して検証する必要があるためです。
信頼untrusted.sequenceのような信頼できないコレクションタイプは、アンダーリングオブジェクトの「ビュー」です。基礎となるオブジェクトが変更された場合、信頼されていないコレクションタイプを介して表示されるオブジェクトも変更されます。言い換えれば、コピーではなく、同じオブジェクトへの参照です。それがあなたが望むものではない場合は、コピーモジュールを使用してください。
これは、このモジュールに固有のものではなく、明らかで不根付いた行動であることを願っていますが、人々をつまずかせることができます。
これはフリーソフトウェア(MITライセンス)です。
untrusted - write safer Python with special untrusted types
Copyright © 2017 - 2018 Ben Golightly <[email protected]>
Copyright © 2017 - 2018 Tawesoft Ltd <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.