最常見的Web應用程序安全弱點是未能從客戶端或環境中正確驗證輸入。
Owasp,數據驗證(2017年7月2日)
無法正確處理不受信任的輸入將使易受代碼注入攻擊的應用程序,例如跨站點腳本(XSS)。 Owasp推薦的一種對策是“客戶或不信任來源的某種形式的可見污染”,這是一項深入的防禦策略的一部分。
這個Python模塊“ Taints”不受信任的輸入將其包裹在特殊類型中。這些類型在大多數方面的行為就像本地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用法。 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
該模塊為懶惰的不信任值的收集提供了類型。這些值用適當的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 ()))有關不信任untrusted.iterator untrusted.string列表,請參見examples/untrustedIteratorExample.py 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映射。 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 ))懶惰的嵌套容器也得到了充分的支持。
使用Un trusted.iteratorof( untrusted.sequenceOf(valueType) untrusted.iteratorOf(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
應用escape_function ,一個函數str -> str它可以通過可選的參數和關鍵字參數來逃脫字符串並將其返回。
untrusted.string.valid(valid_function, [*args, **kwargs]) -> bool
應用valid_function ,一個函數str -> bool ,該函數可以檢查字符串並返回真或錯誤,並使用可選的參數和關鍵字參數。
untrusted.string.valid(validate_function, [*args, **kwargs]) -> any
應用valid_function ,一個函數str -> any ,檢查字符串並返回任何值(例如,字符串未驗證的原因列表),帶有可選的參數和關鍵字參數。
untrusted.string / escape_expr對於某些逃生表達式, untrusted.string("value") / escape_expr -> str
escape_expr在這裡是一個函數str -> str ,可以逃脫字符串,或者是3個支馬(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之一, sequence (列表狀), mapping (類似於dict)或用戶構造的自定義類型。
支持大多數本機收集方法,但可能具有不同的返回類型。
每個集合都知道其價值類型(默認的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 )請記住,僅僅因為您使用了一種方法來逃避untrusted.string方法。彈簧進入str ,它在其他情況下可能並不安全。例如,對HTML的安全可能仍然是危險的SQL。在捕獲用戶輸入時,可能不知道它要使用的上下文 - 因此,尚不知道正確的驗證和逃脫策略是什麼。最好將逃逸延遲到最終使用點 - 保持untrusted.*盡可能長時間。
這個模塊不是神奇的解決方案。這是可以明智使用的工具。不要陷入思考一個價值的陷阱:“現在已經是str ,所以它是完全安全的”。
僅僅因為可以安全地逃脫字符串,這並不意味著它已被驗證為允許輸入。例如,您可能會對密碼提出最小限制。或者您可能要求輸入不是預留的文件名。
做到這一點的好方法是使用unstruted.string.valid方法,該方法返回一個布爾, untrusted.string.validate方法,該方法返回任何值(例如,這可能是輸入沒有valdiate的原因列表),或者從Escapes and Vellate和驗證的函數中拋出ValueError 。
有時,您會自己生成HTML並逃脫是您需要做的事情。
有時,接口總是像大多數現代SQL庫一樣將參數與代碼分開。在這種情況下,數據庫驅動程序將比您希望的更好地處理潛在的不受信任的輸入,並且逃脫是錯誤的。
由於其他原因,您可能會將輸入標記為不信任 - 例如,在搜索查詢上執行最大長度,或者是因為您需要根據業務邏輯進行驗證。
不受信任的收集類型,例如untrusted.sequence序列。如果基礎對象發生了變化,則您通過不信任的收集類型看到的對像也會發生。換句話說:它是對同一對象的引用,而不是副本。如果不是您想要的,請使用複制模塊。
希望這應該是顯而易見的,且不誇張的行為,而不是這個模塊所獨有的,但它可以絆倒人們。
這是免費軟件(麻省理工學院許可證)。
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.