版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第利用Python+eval函數(shù)構(gòu)建數(shù)學(xué)表達(dá)式計(jì)算器目錄eval()的安全問(wèn)題限制globals和locals限制內(nèi)置名稱的使用限制輸入中的名稱將輸入限制為只有字?jǐn)?shù)使用eval()與input()函數(shù)構(gòu)建一個(gè)數(shù)學(xué)表達(dá)式計(jì)算器總結(jié)Python中的函數(shù)eval()?是一個(gè)非常有用的工具,在前期,我們一起學(xué)習(xí)過(guò)該函數(shù)點(diǎn)擊查看:Pythoneval函數(shù)動(dòng)態(tài)地計(jì)算數(shù)學(xué)表達(dá)式?。盡管如此,我們?cè)谑褂弥?,還需要考慮到該函數(shù)的一些重要的安全問(wèn)題。在本文中,云朵君將和大家一起學(xué)習(xí)eval()如何工作,以及如何在Python程序中安全有效地使用它。
eval()的安全問(wèn)題
本節(jié)主要學(xué)習(xí)eval()如何使我們的代碼不安全,以及如何規(guī)避相關(guān)的安全風(fēng)險(xiǎn)。
eval()函數(shù)的安全問(wèn)題在于它允許你(或你的用戶)動(dòng)態(tài)地執(zhí)行任意的Python代碼。
通常情況下,會(huì)存在正在讀(或?qū)懀┑拇a不是我們要執(zhí)行的代碼的情況。如果我們需要使用eval()來(lái)計(jì)算來(lái)自用戶或任何其他外部來(lái)源的輸入,此時(shí)將無(wú)法確定哪些代碼將被執(zhí)行,這將是一個(gè)非常嚴(yán)重的安全漏洞,極易收到黑客的攻擊。
一般情況下,我們并不建議使用eval()。但如果非要使用該函數(shù),需要記住根據(jù)經(jīng)驗(yàn)法則:永遠(yuǎn)不要用未經(jīng)信任的輸入來(lái)使用該函數(shù)。這條規(guī)則的重點(diǎn)在于要弄清楚我們可以信任哪些類型的輸入。
舉個(gè)例子說(shuō)明,隨意使用eval()?會(huì)使我們寫(xiě)的代碼漏洞百出。假設(shè)你想建立一個(gè)在線服務(wù)來(lái)計(jì)算任意的Python數(shù)學(xué)表達(dá)式:用戶自定義表達(dá)式,然后點(diǎn)擊運(yùn)行?按鈕。應(yīng)用程序app獲得用戶的輸入并將其傳遞給eval()進(jìn)行計(jì)算。
這個(gè)應(yīng)用程序app將在我們的個(gè)人服務(wù)器上運(yùn)行,而那些服務(wù)器內(nèi)具有重要文件,如果你在一個(gè)Linux操作系統(tǒng)運(yùn)行命令,并且該進(jìn)程有合法權(quán)限,那么惡意的用戶可以輸入危險(xiǎn)的字符串而損害服務(wù)器,比如下面這個(gè)命令。
"__import__('subprocess').getoutput('rm–rf*')"
上述代碼將刪除程序當(dāng)前目錄中的所有文件。這簡(jiǎn)直太可怕了!
注意:__import__()?是一個(gè)內(nèi)置函數(shù),它接收一個(gè)字符串形式的模塊名稱,并返回一個(gè)模塊對(duì)象的引用。__import__()?是一個(gè)函數(shù),它與導(dǎo)入語(yǔ)句完全不同。我們不能使用eval()來(lái)計(jì)算一個(gè)導(dǎo)入語(yǔ)句。
當(dāng)輸入不受信任時(shí),并沒(méi)有完全有效的方法來(lái)避免eval()?函數(shù)帶來(lái)的安全風(fēng)險(xiǎn)。其實(shí)我們可以通過(guò)限制eval()的執(zhí)行環(huán)境來(lái)減少風(fēng)險(xiǎn)。在下面的內(nèi)容中,我們學(xué)習(xí)一些規(guī)避風(fēng)險(xiǎn)的技巧。
限制globals和locals
可以通過(guò)向globals和locals參數(shù)傳遞自定義字典來(lái)限制eval()?的執(zhí)行環(huán)境。例如,可以給這兩個(gè)參數(shù)傳遞空的字典,以防止eval()訪問(wèn)調(diào)用者當(dāng)前范圍或命名空間中的變量名。
#避免訪問(wèn)調(diào)用者當(dāng)前范圍內(nèi)的名字
x=100
eval("x*5",{},{})
Traceback(mostrecentcalllast):
File"stdin",line1,inmodule
File"string",line1,inmodule
NameError:name'x'isnotdefined
如果給globals和locals傳遞了空的字典({}?),那么eval()?在計(jì)算字符串x*5?時(shí),在它的全局名字空間和局部名字空間都找不到名字x?。因此,eval()將拋出一個(gè)NameError。
然而,像這樣限制globals和locals參數(shù)并不能消除與使用Python的eval()有關(guān)的所有安全風(fēng)險(xiǎn),因?yàn)槿匀豢梢栽L問(wèn)所有Python的內(nèi)置變量名。
限制內(nèi)置名稱的使用
函數(shù)eval()?會(huì)在解析expression之前自動(dòng)將builtins?內(nèi)置模塊字典的引用插入到globals中。使用內(nèi)置函數(shù)__import__()來(lái)訪問(wèn)標(biāo)準(zhǔn)庫(kù)和在系統(tǒng)上安裝的任何第三方模塊。這還容易被惡意用戶利用。
下面的例子表明,即使在限制了globals和locals之后,我們也可以使用任何內(nèi)置函數(shù)和任何標(biāo)準(zhǔn)模塊,如math或subprocess。
eval("sum([5,5,5])",{},{})
eval("__import__('math').sqrt(25)",{},{})
eval("__import__('subprocess').getoutput('echoHello,World')",{},{})
'Hello,World'
我們可以使用__import__()來(lái)導(dǎo)入任何標(biāo)準(zhǔn)或第三方模塊,如導(dǎo)入math和subprocess。因此可以訪問(wèn)在math、subprocess或任何其他模塊中定義的任何函數(shù)或類?,F(xiàn)在想象一下,一個(gè)惡意的用戶可以使用subprocess或標(biāo)準(zhǔn)庫(kù)中任何其他強(qiáng)大的模塊對(duì)系統(tǒng)做什么,那就有點(diǎn)恐怖了。
為了減少這種風(fēng)險(xiǎn),可以通過(guò)覆蓋globals中的__builtins__?鍵來(lái)限制對(duì)Python內(nèi)置函數(shù)的訪問(wèn)。通常建議使用一個(gè)包含鍵值對(duì)__builtins__:{}的自定義字典。
eval("__import__('math').sqrt(25)",{"__builtins__":{}},{})
Traceback(mostrecentcalllast):
File"stdin",line1,inmodule
File"string",line1,inmodule
NameError:name'__import__'isnotdefined
如果我們將一個(gè)包含鍵值對(duì)__builtins__:{}?的字典傳遞給globals,那么eval()?就不能直接訪問(wèn)Python的內(nèi)置函數(shù),比如__import__()。
然而這種方法仍然無(wú)法使得eval()完全規(guī)避風(fēng)險(xiǎn)。
限制輸入中的名稱
即使可以使用自定義的globals?和locals?字典來(lái)限制eval()?的執(zhí)行環(huán)境,這個(gè)函數(shù)仍然會(huì)被攻擊。例如可以使用像、[]、{}或()?來(lái)訪問(wèn)類object以及一些特殊屬性。
"".__class__.__base__
class'object'
[].__class__.__base__
class'object'
{}.__class__.__base__
class'object'
().__class__.__base__
class'object'
一旦訪問(wèn)了object,可以使用特殊的方法`.__subclasses__()`來(lái)訪問(wèn)所有繼承于object的類。下面是它的工作原理。
forsub_classin().__class__.__base__.__subclasses__():
...print(sub_class.__name__)
weakref
weakcallableproxy
weakproxy
...
這段代碼將打印出一個(gè)大類列表。其中一些類的功能非常強(qiáng)大,因此也是一個(gè)重要的安全漏洞,而且我們無(wú)法通過(guò)簡(jiǎn)單地限制eval()的避免該漏洞。
input_string="""[
...cforcin().__class__.__base__.__subclasses__()
...ifc.__name__=="range"
...][0](10"0")"""
list(eval(input_string,{"__builtins__":{}},{}))
[0,1,2,3,4,5,6,7,8,9]
上面代碼中的列表推導(dǎo)式對(duì)繼承自object?的類進(jìn)行過(guò)濾,返回一個(gè)包含range?類的list?。第一個(gè)索引([0]?)返回類的范圍。一旦獲得了對(duì)range?的訪問(wèn)權(quán),就調(diào)用它來(lái)生成一個(gè)range?對(duì)象。然后在range?對(duì)象上調(diào)用list(),從而生成一個(gè)包含十個(gè)整數(shù)的列表。
在這個(gè)例子中,用range?來(lái)說(shuō)明eval()?函數(shù)中的一個(gè)安全漏洞。現(xiàn)在想象一下,如果你的系統(tǒng)暴露了像subprocess.Popen這樣的類,一個(gè)惡意的用戶可以做什么?
我們或許可以通過(guò)限制輸入中的名字的使用,從而解決這個(gè)漏洞。該技術(shù)涉及以下步驟。
創(chuàng)建一個(gè)包含你想用eval()使用的名字的字典。在eval?模式下使用compile()將輸入字符串編譯為字節(jié)碼。檢查字節(jié)碼對(duì)象上的.co_names,以確保它只包含允許的名字。如果用戶試圖輸入一個(gè)不允許的名字,會(huì)引發(fā)一個(gè)`NameError`。
看看下面這個(gè)函數(shù),我們?cè)谄渲袑?shí)現(xiàn)了所有這些步驟。
defeval_expression(input_string):
...#Step1
...allowed_names={"sum":sum}
...#Step2
...code=compile(input_string,"string","eval")
...#Step3
...fornameincode.co_names:
...ifnamenotinallowed_names:
...#Step4
...raiseNameError(f"Useof{name}notallowed")
...returneval(code,{"__builtins__":{}},allowed_names)
eval_expression()?函數(shù)可以在eval()?中使用的名字限制為字典allowed_names?中的那些名字。而該函數(shù)使用了.co_names,它是代碼對(duì)象的一個(gè)屬性,返回一個(gè)包含代碼對(duì)象中的名字的元組。
下面的例子顯示了eval_expression()在實(shí)踐中是如何工作的。
eval_expression("3+4*5+25/2")
eval_expression("sum([1,2,3])")
eval_expression("len([1,2,3])")
Traceback(mostrecentcalllast):
File"stdin",line1,inmodule
File"stdin",line10,ineval_expression
NameError:Useoflennotallowed
eval_expression("pow(10,2)")
Traceback(mostrecentcalllast):
File"stdin",line1,inmodule
File"stdin",line10,ineval_expression
NameError:Useofpownotallowed
如果調(diào)用eval_expression()?來(lái)計(jì)算算術(shù)運(yùn)算,或者使用包含允許的變量名的表達(dá)式,那么將會(huì)正常運(yùn)行并得到預(yù)期的結(jié)果,否則會(huì)拋出一個(gè)`NameError`。上面的例子中,我們僅允許輸入的唯一名字是sum()?,而不允許其他算術(shù)運(yùn)算名稱如len()和pow(),所以當(dāng)使用它們時(shí),該函數(shù)會(huì)產(chǎn)生一個(gè)`NameError`。
如果完全不允許使用名字,那么可以把eval_expression()改寫(xiě):
defeval_expression(input_string):
...code=compile(input_string,"string","eval")
...ifcode.co_names:
...raiseNameError(f"Useofnamesnotallowed")
...returneval(code,{"__builtins__":{}},{})
eval_expression("3+4*5+25/2")
eval_expression("sum([1,2,3])")
Traceback(mostrecentcalllast):
File"stdin",line1,inmodule
File"stdin",line4,ineval_expression
NameError:Useofnamesnotallowed
現(xiàn)在函數(shù)不允許在輸入字符串中出現(xiàn)任何變量名。需要檢查.co_names?中的變量名,一旦發(fā)現(xiàn)就引發(fā)NameError。否則計(jì)算input_string?并返回計(jì)算的結(jié)果。此時(shí)也使用一個(gè)空的字典來(lái)限制locals。
我們可以使用這種技術(shù)來(lái)盡量減少eval()的安全問(wèn)題,并加強(qiáng)安全盔甲,防止惡意攻擊。
將輸入限制為只有字?jǐn)?shù)
函數(shù)eval()的一個(gè)常見(jiàn)用例是計(jì)算包含標(biāo)準(zhǔn)Python字面符號(hào)的字符串,并將其變成具體的對(duì)象。
標(biāo)準(zhǔn)庫(kù)提供了一個(gè)叫做literal_eval()的函數(shù),可以幫助實(shí)現(xiàn)這個(gè)目標(biāo)。雖然這個(gè)函數(shù)不支持運(yùn)算符,但它支持list,tuples,numbers,strings等等。
fromastimportliteral_eval
#計(jì)算字面意義
literal_eval("15.02")
15.02
literal_eval("[1,15]")
[1,15]
literal_eval("(1,15)")
(1,15)
literal_eval("{'one':1,'two':2}")
{'one':1,'two':2}
#試圖計(jì)算一個(gè)表達(dá)式
literal_eval("sum([1,15])+5+8*2")
Traceback(mostrecentcalllast):
ValueError:malformednodeorstring:_ast.BinOpobjectat0x7faedecd7668
注意,literal_eval()?只作用于標(biāo)準(zhǔn)類型的字詞。它不支持使用運(yùn)算符或變量名。如果向literal_eval()?傳遞一個(gè)表達(dá)式,會(huì)得到一個(gè)ValueError。這個(gè)函數(shù)還可以將與使用eval()有關(guān)的安全風(fēng)險(xiǎn)降到最低。
使用eval()與input()函數(shù)
在Python3.x中,內(nèi)置函數(shù)input()讀取命令行上的用戶輸入,去掉尾部的換行,轉(zhuǎn)換為字符串,并將結(jié)果返回給調(diào)用者。由于input()?的輸出結(jié)果是一個(gè)字符串,可以把它傳遞給eval()并作為一個(gè)Python表達(dá)式來(lái)計(jì)算它。
eval(input("Enteramathexpression:"))
Enteramathexpression:15*2
eval(input("Enteramathexpression:"))
Enteramathexpression:5+8
13
我們可以將函數(shù)eval()?包裹在函數(shù)input()?中,實(shí)現(xiàn)自動(dòng)計(jì)算用戶的輸入的功能。一個(gè)常見(jiàn)用例模擬Python2.x中input()?的行為,input()將用戶的輸入作為一個(gè)Python表達(dá)式來(lái)計(jì)算,并返回結(jié)果。
因?yàn)樗婕鞍踩珕?wèn)題,因此在Python2.x中的input()的這種行為在Python3.x中被改變了。
構(gòu)建一個(gè)數(shù)學(xué)表達(dá)式計(jì)算器
到目前為止,我們已經(jīng)了解了函數(shù)eval()?是如何工作的以及如何在實(shí)踐中使用它。此外還了解到eval()?具有重要的安全漏洞,盡量在代碼中避免使用eval()?,然而在某些情況下,eval()?可以為我們節(jié)省大量的時(shí)間和精力。因此,學(xué)會(huì)合理使用eval()函數(shù)還是蠻重要的。
在本節(jié)中,將編寫(xiě)一個(gè)應(yīng)用程序來(lái)動(dòng)態(tài)地計(jì)算數(shù)學(xué)表達(dá)式。首先不使用eval()來(lái)解決這個(gè)問(wèn)題,那么需要通過(guò)以下步驟:
解析輸入的表達(dá)式。將表達(dá)式的組成部分變?yōu)镻ython對(duì)象(數(shù)字、運(yùn)算符、函數(shù)等等)。將所有的東西合并成一個(gè)表達(dá)式。確認(rèn)該表達(dá)式在Python中是有效的。計(jì)算最終表達(dá)式并返回結(jié)果。
考慮到Python可以處理和計(jì)算的各種表達(dá)式非常耗時(shí)。其實(shí)我們可以使用eval()來(lái)解決這個(gè)問(wèn)題,而且通過(guò)上文我們已經(jīng)學(xué)會(huì)了幾種技術(shù)來(lái)規(guī)避相關(guān)的安全風(fēng)險(xiǎn)。
首先創(chuàng)建一個(gè)新的Python腳本,名為mathrepl.py,然后添加以下代碼。
importmath
__version__="1.0"
ALLOWED_NAMES={
k:vfork,vinmath.__dict__.items()ifnotk.startswith("__")
PS1="mr"
WELCOME=f"""
MathREPL{__version__},yourPythonmathexpressionsevaluator!
Enteravalidmathexpressionaftertheprompt"{PS1}".
Type"help"formoreinformation.
Type"quit"or"exit"toexit.
USAGE=f"""
Usage:
Buildmathexpressionsusingnumericvaluesandoperators.
Useanyofthefollowingfunctionsandconstants:
{','.join(ALLOWED_NAMES.keys())}
"""
在這段代碼中,我們首先導(dǎo)入math模塊。這個(gè)模塊使用預(yù)定義的函數(shù)和常數(shù)進(jìn)行數(shù)學(xué)運(yùn)算。常量ALLOWED_NAMES?保存了一個(gè)包含數(shù)學(xué)中非特變量名的字典。這樣就可以用eval()來(lái)使用它們。
我們還定義了另外三個(gè)字符串常量。將使用它們作為腳本的用戶界面,并根據(jù)需要打印到屏幕上。
現(xiàn)在準(zhǔn)備編寫(xiě)核心功能,首先編寫(xiě)一個(gè)函數(shù),接收數(shù)學(xué)表達(dá)式作為輸入,并返回其結(jié)果。此外還需要寫(xiě)一個(gè)叫做evaluate()的函數(shù),如下所示。
defevaluate(expression):
"""Evaluateamathexpression."""
#編譯表達(dá)式
code=compile(expression,"string","eval")
#驗(yàn)證允許名稱
fornameincode.co_names:
ifnamenotinALLOWED_NAMES:
raiseNameError(f"Theuseof'{name}'isnotallowed")
returneval(code,{"__builtins__":{}},ALLOWED_NAMES)
以下是該功能的工作原理。
定義了evaluate(),該函數(shù)將字符串表達(dá)式作為參數(shù),并返回一個(gè)浮點(diǎn)數(shù),代表將字符串作為數(shù)學(xué)表達(dá)式進(jìn)行計(jì)算的結(jié)果。使用compile()將輸入的字符串表達(dá)式變成編譯的Python代碼。如果用戶輸入了一個(gè)無(wú)效的表達(dá)式,編譯操作將引發(fā)一個(gè)SyntaxError。使用一個(gè)for循環(huán),檢查表達(dá)式中包含的名字,并確認(rèn)它們可以在最終表達(dá)式中使用。如果用戶提供的名字不在允許的名字列表中,那么會(huì)引發(fā)一個(gè)NameError。執(zhí)行數(shù)學(xué)表達(dá)式的實(shí)際計(jì)算。注意將自定義的字典傳遞給了globals和locals。ALLOWED_NAMES保存了數(shù)學(xué)中定義的函數(shù)和常量。
注意:由于這個(gè)應(yīng)用程序使用了math中定義的函數(shù),需要注意,當(dāng)我們用一個(gè)無(wú)效的輸入值調(diào)用這些函數(shù)時(shí),其中一些函數(shù)將拋出ValueError異常。
例如,math.sqrt(-10)?會(huì)引發(fā)一個(gè)異常,因?yàn)?10的平方根是未定義的。我們會(huì)在稍后的代碼中看到如何捕捉該異常。
為globals和locals參數(shù)使用自定義值,加上名稱檢查,可以將與使用eval()有關(guān)的安全風(fēng)險(xiǎn)降到最低。
當(dāng)在main()中編寫(xiě)其代碼時(shí),數(shù)學(xué)表達(dá)式計(jì)算器就完成了。在這個(gè)函數(shù)中,定義程序的主循環(huán),結(jié)束讀取和計(jì)算用戶在命令行中輸入的表達(dá)式的循環(huán)。
在這個(gè)例子中,應(yīng)用程序?qū)ⅲ?/p>
向用戶打印一條歡迎信息顯示一個(gè)提示,準(zhǔn)備讀取用戶的輸入提供獲取使用說(shuō)明和終止應(yīng)用程序的選項(xiàng)讀取用戶的數(shù)學(xué)表達(dá)式計(jì)算用戶的數(shù)學(xué)表達(dá)式將計(jì)算的結(jié)果打印到屏幕上
defmain():
"""Mainloop:Readandevaluateuser'sinput."""
print(WELCOME)
whileTrue:
#讀取用戶的輸入
try:
expression=input(f"{PS1}")
except(KeyboardInterrupt,EOFError):
raiseSystemExit()
#處理特殊命令
ifexpression.lower()=="help":
print(USAGE)
continue
ifexpression.lower()in{"quit","exit"}:
raiseSystemExit()
#對(duì)表達(dá)式進(jìn)行計(jì)算并處理錯(cuò)誤
try:
result=evaluate(expression)
exceptSyntaxError:
#如果用戶輸入了一個(gè)無(wú)效的表達(dá)式
print("Invalidinputexpressionsyntax")
continue
except(NameError,ValueError)aserr:
#如果用戶試圖使用一個(gè)不允許的名字
#對(duì)于一個(gè)給定的數(shù)學(xué)函數(shù)來(lái)說(shuō)是一個(gè)無(wú)效的值
print(err)
continue
#如果沒(méi)有發(fā)生錯(cuò)誤,則打印結(jié)果
print(f"Theresultis:{result}")
if__name__=="__main__":
main()
在main()?中,首先打印WELCOME消息。然后在一個(gè)try語(yǔ)句中讀取用戶的輸入,以捕獲鍵盤(pán)中斷和EOFError。如果這些異常發(fā)生,就終止應(yīng)用程序。
如果用戶輸入幫助選項(xiàng),那么應(yīng)用程序就會(huì)顯示使用指南。同樣地,如果用戶輸入quit或exit,那么應(yīng)用程序就會(huì)終止。
最后,使用evaluate()?來(lái)計(jì)算用戶的數(shù)學(xué)表達(dá)式,然后將結(jié)果打印到屏幕上。值得注意的是,對(duì)evaluate()的調(diào)用會(huì)引發(fā)以下異常。
SyntaxError:語(yǔ)法錯(cuò)誤,當(dāng)用戶輸入一個(gè)不符合Python語(yǔ)法的表達(dá)式時(shí),就會(huì)發(fā)生這種情況。NameError:當(dāng)用戶試圖使用一個(gè)不允許的名稱(函數(shù)、類或?qū)傩裕r(shí),就會(huì)發(fā)生這種情況。ValueError:當(dāng)用戶試圖使用一個(gè)不允許的值作為數(shù)學(xué)中某個(gè)函數(shù)的輸入時(shí),就會(huì)發(fā)生這種情況。
注意,在main()中,捕捉了所有已知異常,并相應(yīng)地打印信息給用戶。這將使用戶能夠?qū)彶楸?/p>
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 雨水管網(wǎng)自動(dòng)化監(jiān)測(cè)方案
- 道路工程風(fēng)險(xiǎn)評(píng)估方案
- 道路通行能力提升方案
- 地基承載力檢測(cè)與評(píng)估方案
- 建筑物排水系統(tǒng)維護(hù)方案
- 2026年人工智能在交通領(lǐng)域的應(yīng)用考試題庫(kù)答案
- 2026年游戲開(kāi)發(fā)項(xiàng)目時(shí)間規(guī)劃專項(xiàng)試題
- 消防設(shè)施信息化建設(shè)方案
- 消防安全文化推廣方案
- 防腐蝕工程安全隱患排查方案
- 設(shè)備安裝施工應(yīng)急預(yù)案
- 拼多多會(huì)計(jì)課件
- 卡西歐手表WVA-M600(5161)中文使用說(shuō)明書(shū)
- 電力高處作業(yè)培訓(xùn)
- 人臉門(mén)禁系統(tǒng)管理制度
- 辦公設(shè)備清單表格
- 環(huán)保隱患分級(jí)管理制度
- 《鐵路運(yùn)輸調(diào)度》課件全套 孫建暉 第1-5章 貨物列車(chē)編組計(jì)劃- 調(diào)度工作分析
- 三力測(cè)試題庫(kù)200題及答案
- 董事委任協(xié)議書(shū)
- 電商客服知識(shí)考試試題及答案
評(píng)論
0/150
提交評(píng)論