0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python項(xiàng)目中遇到的10個(gè)安全陷阱

科技綠洲 ? 來源:Python貓 ? 作者:Python貓 ? 2023-10-30 10:34 ? 次閱讀

Python 開發(fā)者們在使用標(biāo)準(zhǔn)庫和通用框架時(shí),都以為自己的程序具有可靠的安全性。然而,在 Python 中,就像在任何其它編程語言中一樣,有一些特性可能會(huì)被開發(fā)者們誤解或誤用。通常而言,只有極少的微妙之處或細(xì)節(jié)會(huì)使開發(fā)者們疏忽大意,從而在代碼中引入嚴(yán)重的安全漏洞。

在這篇博文中,我們將分享在實(shí)際 Python 項(xiàng)目中遇到的 10 個(gè)安全陷阱。我們選擇了一些在技術(shù)圈中不太為人所知的陷阱。通過介紹每個(gè)問題及其造成的影響,我們希望提高人們對這些問題的感知,并提高大家的安全意識(shí)。如果你正在使用這些特性,請一定要排查你的 Python 代碼!

1.被優(yōu)化掉的斷言

Python 支持以優(yōu)化的方式執(zhí)行代碼。這使代碼運(yùn)行得更快,內(nèi)存用得更少。當(dāng)程序被大規(guī)模使用,或者可用的資源很少時(shí),這種方法尤其有效。一些預(yù)打包的 Python 程序提供了優(yōu)化的字節(jié)碼。

然而,當(dāng)代碼被優(yōu)化時(shí),所有的 assert 語句都會(huì)被忽略。開發(fā)者有時(shí)會(huì)使用它們來判斷代碼中的某些條件。例如,如果使用斷言來作身份驗(yàn)證檢查,則可能導(dǎo)致安全繞過。

def superuser_action(request, user):
    assert user.is_super_user
    # execute action as super user

在這個(gè)例子中,第 2 行中的 assert 語句將被忽略,導(dǎo)致非超級(jí)用戶也可以運(yùn)行到下一行代碼。不推薦使用 assert 語句進(jìn)行安全相關(guān)的檢查,但我們確實(shí)在實(shí)際的項(xiàng)目中看到過它們。

2. MakeDirs 權(quán)限

os.makdirs 函數(shù)可以在操作系統(tǒng)中創(chuàng)建一個(gè)或多個(gè)文件夾。它的第二個(gè)參數(shù) mode 用于指定創(chuàng)建的文件夾的默認(rèn)權(quán)限。在下面代碼的第 2 行中,文件夾 A/B/C 是用 rwx------ (0o700) 權(quán)限創(chuàng)建的。這意味著只有當(dāng)前用戶(所有者)擁有這些文件夾的讀、寫和執(zhí)行權(quán)限。

def init_directories(request):
    os.makedirs("A/B/C", mode=0o700)
    return HttpResponse("Done!")

在 Python < 3.6 版本中,創(chuàng)建出的文件夾 A、B 和 C 的權(quán)限都是 700。但是,在 Python > 3.6 版本中,只有最后一個(gè)文件夾 C 的權(quán)限為 700,其它文件夾 A 和 B 的權(quán)限為默認(rèn)的 755。

因此,在 Python > 3.6 中,os.makdirs 函數(shù)等價(jià)于 Linux 的這條命令:mkdir -m 700 -p A/B/C。有些開發(fā)者沒有意識(shí)到版本之間的差異,這已經(jīng)在 Django 中造成了一個(gè)權(quán)限越級(jí)漏洞(cve - 2022 -24583),無獨(dú)有偶,這在 WordPress 中也造成了一個(gè)加固繞過問題。

3.絕對路徑拼接

os.path.join(path, *paths) 函數(shù)用于將多個(gè)文件路徑連接成一個(gè)組合的路徑。第一個(gè)參數(shù)通常包含了基礎(chǔ)路徑,而之后的每個(gè)參數(shù)都被當(dāng)做組件拼接到基礎(chǔ)路徑后。

然而,這個(gè)函數(shù)有一個(gè)少有人知的特性。如果拼接的某個(gè)路徑以 / 開頭,那么包括基礎(chǔ)路徑在內(nèi)的所有前綴路徑都將被刪除,該路徑將被視為絕對路徑。下面的示例揭示了開發(fā)者可能遇到的這個(gè)陷阱。

def read_file(request):
    filename = request.POST['filename']
    file_path = os.path.join("var", "lib", filename)
    if file_path.find(".") != -1:
        return HttpResponse("Failed!")
    with open(file_path) as f:
        return HttpResponse(f.read(), content_type='text/plain')

在第 3 行中,我們使用 os.path.join 函數(shù)將用戶輸入的文件名構(gòu)造出目標(biāo)路徑。在第 4 行中,檢查生成的路徑是否包含”.“,防止出現(xiàn)路徑遍歷漏洞。

但是,如果攻擊者傳入的文件名參數(shù)為”/a/b/c.txt“,那么第 3 行得到的變量 file_path 會(huì)是一個(gè)絕對路徑(/a/b/c.txt)。即 os.path.join 會(huì)忽略掉”var/lib“部分,攻擊者可以不使用“.”字符就讀取到任何文件。盡管 os.path.join 的文檔中描述了這種行為,但這還是導(dǎo)致了許多漏洞(Cuckoo Sandbox Evasion, CVE-2020-35736)。

4. 任意的臨時(shí)文件

tempfile.NamedTemporaryFile 函數(shù)用于創(chuàng)建具有特定名稱的臨時(shí)文件。但是,prefix(前綴)和 suffix(后綴)參數(shù)很容易受到路徑遍歷攻擊(Issue 35278)。如果攻擊者控制了這些參數(shù)之一,他就可以在文件系統(tǒng)中的任意位置創(chuàng)建出一個(gè)臨時(shí)文件。下面的示例揭示了開發(fā)者可能遇到的一個(gè)陷阱。

def touch_tmp_file(request):
    id = request.GET['id']
    tmp_file = tempfile.NamedTemporaryFile(prefix=id)
    return HttpResponse(f"tmp file: {tmp_file} created!", content_type='text/plain')

在第 3 行中,用戶輸入的 id 被當(dāng)作臨時(shí)文件的前綴。如果攻擊者傳入的 id 參數(shù)是“/../var/www/test”,則會(huì)創(chuàng)建出這樣的臨時(shí)文件:/var/www/test_zdllj17。粗看起來,這可能是無害的,但它會(huì)為攻擊者創(chuàng)造出挖掘更復(fù)雜的漏洞的基礎(chǔ)。

5.擴(kuò)展的 Zip Slip

在 Web 應(yīng)用中,通常需要解壓上傳后的壓縮文件。在 Python 中,很多人都知道 TarFile.extractall 與 TarFile.extract 函數(shù)容易受到 Zip Slip 攻擊。攻擊者通過篡改壓縮包中的文件名,使其包含路徑遍歷(../)字符,從而發(fā)起攻擊。

這就是為什么壓縮文件應(yīng)該始終被視為不受信來源的原因。zipfile.extractall 與 zipfile.extract 函數(shù)可以對 zip 內(nèi)容進(jìn)行清洗,從而防止這類路徑遍歷漏洞。

但是,這并不意味著在 ZipFile 庫中不會(huì)出現(xiàn)路徑遍歷漏洞。下面是一段解壓縮文件的代碼。

def extract_html(request):
    filename = request.FILES['filename']
    zf = zipfile.ZipFile(filename.temporary_file_path(), "r")
    for entry in zf.namelist():
        if entry.endswith(".html"):
            file_content = zf.read(entry)
            with open(entry, "wb") as fp:
                fp.write(file_content)
    zf.close()
    return HttpResponse("HTML files extracted!")

第 3 行代碼根據(jù)用戶上傳文件的臨時(shí)路徑,創(chuàng)建出一個(gè) ZipFile 處理器。第 4 - 8 行代碼將所有以“.html”結(jié)尾的壓縮項(xiàng)提取出來。第 4 行中的 zf.namelist 函數(shù)會(huì)取到 zip 內(nèi)壓縮項(xiàng)的名稱。注意,只有 zipfile.extract 與 zipfile.extractall 函數(shù)會(huì)對壓縮項(xiàng)進(jìn)行清洗,其它任何函數(shù)都不會(huì)。

在這種情況下,攻擊者可以創(chuàng)建一個(gè)文件名,例如“../../../var/www/html”,內(nèi)容隨意填。該惡意文件的內(nèi)容會(huì)在第 6 行被讀取,并在第 7-8 行寫入被攻擊者控制的路徑。因此,攻擊者可以在整個(gè)服務(wù)器上創(chuàng)建任意的 HTML 文件。

如上所述,壓縮包中的文件應(yīng)該被看作是不受信任的。如果你不使用 zipfile.extractall 或者 zipfile.extract,你就必須對 zip 內(nèi)文件的名稱進(jìn)行“消毒”,例如使用 os.path.basename。否則,它可能導(dǎo)致嚴(yán)重的安全漏洞,就像在 NLTK Downloader (CVE-2019-14751)中發(fā)現(xiàn)的那樣。

6. 不完整的正則表達(dá)式匹配

正則表達(dá)式(regex)是大多數(shù) Web 程序不可或缺的一部分。我們經(jīng)常能看到它被自定義的 Web 應(yīng)用防火墻(WAF,Web Application Firewalls)用來作輸入驗(yàn)證,例如檢測惡意字符串。在 Python 中,re.match 和 re.search 之間有著細(xì)微的區(qū)別,我們將在下面的代碼片段中演示。

def is_sql_injection(request):
    pattern = re.compile(r".*(union)|(select).*")
    name_to_test = request.GET['name']
    if re.search(pattern, name_to_test):
        return True
    return False

在第 2 行中,我們定義了一個(gè)匹配 union 或者 select 的模式,以檢測可能的 SQL 注入。這是一個(gè)糟糕的寫法,因?yàn)槟憧梢暂p易地繞過這些黑名單,但我們已經(jīng)在線上的程序中見過它。在第 4 行中,函數(shù) re.match 使用前面定義好的模式,檢查第 3 行中的用戶輸入內(nèi)容是否包含這些惡意的值。

然而,與 re.search 函數(shù)不同的是,re.match 函數(shù)不匹配新行。例如,如果攻擊者提交了值 aaaaaa n union select,這個(gè)輸入就匹配不上正則表達(dá)式。因此,檢查可以被繞過,失去保護(hù)作用。

總而言之,我們不建議使用正則表達(dá)式黑名單進(jìn)行任何安全檢查。

7. Unicode 清洗器繞過

Unicode 支持用多種形式來表示字符,并將這些字符映射到碼點(diǎn)。在 Unicode 標(biāo)準(zhǔn)中,不同的 Unicode 字符有四種歸一化方案。程序可以使用這些歸一化方法,以獨(dú)立于人類語言的標(biāo)準(zhǔn)方式來存儲(chǔ)數(shù)據(jù),例如用戶名。

然而,攻擊者可以利用這些歸一化,這已經(jīng)導(dǎo)致了 Python 的 urllib 出現(xiàn)漏洞(CVE-2019-9636)。下面的代碼片段演示了一個(gè)基于 NFKC 歸一化的跨站點(diǎn)腳本漏洞(XSS,Cross-Site Scripting)。

import unicodedata
from django.shortcuts import render
from django.utils.html import escape

def render_input(request):
    user_input = escape(request.GET['p'])
    normalized_user_input = unicodedata.normalize("NFKC", user_input)
    context = {'my_input': normalized_user_input}
    return render(request, 'test.html', context)

在第 6 行中,用戶輸入的內(nèi)容被 Django 的 escape 函數(shù)處理了,以防止 XSS 漏洞。在第 7 行中,經(jīng)過清洗的輸入被 NFKC 算法歸一化,以便在第 8-9 行中通過 test.html 模板正確地渲染。

templates/test.html

< !DOCTYPE html >
< html lang="en" >
< body >
{{ my_input | safe}}
< /body >
< /html >

在模板 test.html 中,第 4 行的變量 my_input 被標(biāo)記為安全的,因?yàn)殚_發(fā)人員預(yù)期有特殊字符,并且認(rèn)為該變量已經(jīng)被 escape 函數(shù)清洗了。通過標(biāo)記關(guān)鍵字 safe, Django 不會(huì)再次對變量進(jìn)行清洗。

但是,由于第 7 行(view.py)的歸一化,字符“%EF%B9%A4”會(huì)被轉(zhuǎn)換為“<”,“%EF%B9%A5”被轉(zhuǎn)換為“>”。這導(dǎo)致攻擊者可以注入任意的 HTML 標(biāo)記,進(jìn)而觸發(fā) XSS 漏洞。為了防止這個(gè)漏洞,就應(yīng)該在把用戶輸入做完歸一化之后,再進(jìn)行清洗。

8. Unicode 編碼碰撞

前文說過,Unicode 字符會(huì)被映射成碼點(diǎn)。然而,有許多不同的人類語言,Unicode 試圖將它們統(tǒng)一起來。這就意味著不同的字符很有可能擁有相同的“l(fā)ayout”。例如,小寫的土耳其語 ?(沒有點(diǎn))的字符是英語中大寫的 I。在拉丁字母中,字符 i 也是用大寫的 I 表示。在 Unicode 標(biāo)準(zhǔn)中,這兩個(gè)不同的字符都以大寫形式映射到同一個(gè)碼點(diǎn)。

這種行為是可以被利用的,實(shí)際上已經(jīng)在 Django 中導(dǎo)致了一個(gè)嚴(yán)重的漏洞(CVE-2019-19844)。下面的代碼是一個(gè)重置密碼的示例。

from django.core.mail import send_mail
from django.http import HttpResponse
from vuln.models import User

def reset_pw(request):
    email = request.GET['email']
    result = User.objects.filter(email__exact=email.upper()).first()
    if not result:
        return HttpResponse("User not found!")
    send_mail('Reset Password','Your new pw: 123456.', 'from@example.com', [email], fail_silently=False)
    return HttpResponse("Password reset email send!")

第 6 行代碼獲取了用戶輸入的 email,第 7-9 行代碼檢查這個(gè) email 值,查找是否存在具有該 email 的用戶。如果用戶存在,則第 10 行代碼依據(jù)第 6 行中輸入的 email 地址,給用戶發(fā)送郵件。需要指出的是,第 7-9 行中對郵件地址的檢查是不區(qū)分大小寫的,使用了 upper 函數(shù)。

至于攻擊,我們假設(shè)數(shù)據(jù)庫中存在一個(gè)郵箱地址為 foo@mix.com 的用戶。那么,攻擊者可以簡單地傳入 foo@m?x.com 作為第 6 行中的 email,其中 i 被替換為土耳其語 ?。第 7 行代碼將郵箱轉(zhuǎn)換成大寫,結(jié)果是 FOO@MIX.COM。這意味著找到了一個(gè)用戶,因此會(huì)發(fā)送一封重置密碼的郵件。

然而,郵件被發(fā)送到第 6 行未轉(zhuǎn)換的郵件地址,也就是包含了土耳其語的 ?。換句話說,其他用戶的密碼被發(fā)送到了攻擊者控制的郵件地址。為了防止這個(gè)漏洞,可以將第 10 行替換成使用數(shù)據(jù)庫中的用戶郵箱。即使發(fā)生編碼沖突,攻擊者在這種情況下也得不到任何好處。

9. IP 地址歸一化

在 Python < 3.8 中,IP 地址會(huì)被 ipaddress 庫歸一化,因此前綴的零會(huì)被刪除。這種行為乍一看可能是無害的,但它已經(jīng)在 Django 中導(dǎo)致了一個(gè)高嚴(yán)重性的漏洞(CVE-2021-33571)。攻擊者可以利用歸一化繞過校驗(yàn)程序,發(fā)起服務(wù)端請求偽造攻擊(SSRF,Server-Side Request Forgery)。

下面的代碼展示了如何繞過這樣的校驗(yàn)器。

import requests
import ipaddress

def send_request(request):
    ip = request.GET['ip']
    try:
        if ip in ["127.0.0.1", "0.0.0.0"]:
            return HttpResponse("Not allowed!")
        ip = str(ipaddress.IPv4Address(ip))
    except ipaddress.AddressValueError:
        return HttpResponse("Error at validation!")
    requests.get('https://' + ip)
    return HttpResponse("Request send!")

第 5 行代碼獲取用戶傳入的一個(gè) IP 地址,第 7 行代碼使用一個(gè)黑名單來檢查該 IP 是否為本地地址,以防止可能的 SSRF 漏洞。這份黑名單并不完整,僅作為示例。

第 9 行代碼檢查該 IP 是否為 IPv4 地址,同時(shí)將 IP 歸一化。在完成驗(yàn)證后,第 12 行代碼會(huì)對該 IP 發(fā)起實(shí)際的請求。

但是,攻擊者可以傳入 127.0.001 這樣的 IP 地址,在第 7 行的黑名單列表中找不到。然后,第 9 行代碼使用 ipaddress.IPv4Address 將 IP 歸一化為 127.0.0.1。因此,攻擊者就能夠繞過 SSRF 校驗(yàn)器,并向本地網(wǎng)絡(luò)地址發(fā)送請求。

10. URL 查詢參數(shù)解析

在 Python < 3.7 中,urllib.parse.parse_qsl 函數(shù)允許使用“;”和“&”字符作為 URL 的查詢變量的分隔符。有趣的是“;”字符不能被其它語言識(shí)別為分隔符。

在下面的例子中,我們將展示為什么這種行為會(huì)導(dǎo)致漏洞。假設(shè)我們正在運(yùn)行一個(gè)基礎(chǔ)設(shè)施,其中前端是一個(gè) PHP 程序,后端則是一個(gè) Python 程序。

攻擊者向 PHP 前端發(fā)送以下的 GET 請求:

GET https://victim.com/?a=1;b=2

PHP 前端只識(shí)別出一個(gè)查詢參數(shù)“a”,其內(nèi)容為“1;b=2”。PHP 不把“;”字符作為查詢參數(shù)的分隔符?,F(xiàn)在,前端會(huì)將攻擊者的請求直接轉(zhuǎn)發(fā)給內(nèi)部的 Python 程序:

GET https://internal.backend/?a=1;b=2

如果使用了 urllib.parse.parse_qsl,Python 程序會(huì)處理成兩個(gè)查詢參數(shù),即“a=1”和“b=2”。這種查詢參數(shù)解析的差異可能會(huì)導(dǎo)致致命的安全漏洞,比如 Django 中的 Web 緩存投毒漏洞(CVE-2021-23336)。

總結(jié)

在這篇博文中,我們介紹了 10 個(gè) Python 安全陷阱,我們認(rèn)為開發(fā)者不太了解它們。每個(gè)細(xì)微的陷阱都很容易被忽視,并在過去導(dǎo)致了線上程序的安全漏洞。

正如前文所述,安全陷阱可能出現(xiàn)在各種操作中,從處理文件、目錄、壓縮文件、URL、IP 到簡單的字符串。一種常見的情況是庫函數(shù)的使用,這些函數(shù)可能有意想不到的行為。這提醒我們一定要升級(jí)到最新版本,并仔細(xì)閱讀文檔。在 SonarSource 中,我們正在研究這些缺陷,以便將來不斷改進(jìn)我們的代碼分析器。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2975

    瀏覽量

    73815
  • 程序
    +關(guān)注

    關(guān)注

    116

    文章

    3761

    瀏覽量

    80754
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4722

    瀏覽量

    68236
  • python
    +關(guān)注

    關(guān)注

    55

    文章

    4767

    瀏覽量

    84376
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Python 中少為人知的 10 個(gè)安全陷阱(上)

    極少的微妙之處或細(xì)節(jié)會(huì)使開發(fā)者們疏忽大意,從而在代碼中引入嚴(yán)重的安全漏洞。在這篇博文中,我們將分享在實(shí)際 Python 項(xiàng)目中遇到10
    發(fā)表于 03-24 16:43

    Python 中少為人知的 10 個(gè)安全陷阱(下)

    處理成兩個(gè)查詢參數(shù),即“a=1”和“b=2”。這種查詢參數(shù)解析的差異可能會(huì)導(dǎo)致致命的安全漏洞,比如 Django 中的 Web 緩存投毒漏洞(CVE-2021-23336)。總結(jié)我們介紹了 10
    發(fā)表于 03-24 16:46

    Python項(xiàng)目標(biāo)準(zhǔn)結(jié)構(gòu)推薦

    在真正項(xiàng)目中,一般使用PyCharm或VSCode開發(fā)。那有的小伙伴就問了,項(xiàng)目文件目錄有沒有一個(gè)標(biāo)準(zhǔn)的結(jié)構(gòu)?應(yīng)該沒有唯一的統(tǒng)一標(biāo)準(zhǔn),但Python社區(qū)大佬Kenneth Reitz在
    發(fā)表于 03-28 15:56

    如何將visualAudio設(shè)計(jì)加進(jìn)項(xiàng)目中

    的設(shè)計(jì)應(yīng)用到項(xiàng)目中,如圖: 我主要是用SHARP系列的,369,489 想要這樣的設(shè)計(jì)圖應(yīng)用到項(xiàng)目中要怎樣,去做呢? 是否只能用VDSP++去加到項(xiàng)目,CCES可以否? 要怎樣設(shè)置配置工程? 想要一
    發(fā)表于 11-30 08:01

    使用Method Swizzling遇到的問題和項(xiàng)目中使用的Swizzling方案

    導(dǎo)語:Method Swizzling是Objective-C中運(yùn)行時(shí)中討論較多的內(nèi)容,本文主要介紹使用Method Swizzling遇到的問題和項(xiàng)目中使用的Swizzling方案。 一
    發(fā)表于 09-22 19:35 ?0次下載
    使用Method Swizzling<b class='flag-5'>遇到</b>的問題和<b class='flag-5'>項(xiàng)目中</b>使用的Swizzling方案

    精選10個(gè)Python開源項(xiàng)目

    過去一個(gè)月里,我們對近 250 個(gè) Python 開源項(xiàng)目進(jìn)行了排名,并挑選出熱度前 10項(xiàng)目
    的頭像 發(fā)表于 11-12 09:47 ?6288次閱讀

    最新Python學(xué)習(xí)熱度前10項(xiàng)目

    Geospatial 是一個(gè)基于 Python 的地理空間數(shù)據(jù)項(xiàng)目。在該項(xiàng)目中,你可以了解到兩個(gè)用于地理空間數(shù)據(jù)處理的
    的頭像 發(fā)表于 11-19 09:36 ?2636次閱讀

    python初學(xué)者會(huì)遇到的29個(gè)操作難點(diǎn)

    初學(xué)Python的人總會(huì)遇到這樣或者那樣的問題,在我學(xué)習(xí)Python的這段時(shí)間我總結(jié)了自己的29個(gè)問題。
    的頭像 發(fā)表于 12-28 17:08 ?2566次閱讀

    Python在嵌入式項(xiàng)目中的輔助開發(fā)總結(jié)

    Python在嵌入式項(xiàng)目中的輔助開發(fā)總結(jié)(嵌入式開發(fā)試題)-該文檔為Python在嵌入式項(xiàng)目中的輔助開發(fā)總結(jié)文檔,是一份很不錯(cuò)的參考資料,具有較高參考價(jià)值,感興趣的可以下載看看…………
    發(fā)表于 08-04 10:11 ?5次下載
    <b class='flag-5'>Python</b>在嵌入式<b class='flag-5'>項(xiàng)目中</b>的輔助開發(fā)總結(jié)

    10具有挑戰(zhàn)性的Python項(xiàng)目創(chuàng)意

    你知道 Python 是被稱為 全能編程語言 的嗎?是的,它確實(shí)是,雖然不應(yīng)該在每個(gè)項(xiàng)目中都使用它。你可以使用它來創(chuàng)建桌面應(yīng)用程序、游戲、移動(dòng)應(yīng)用程序、網(wǎng)站和系統(tǒng)軟件。它甚至是最適合用于實(shí)現(xiàn)
    的頭像 發(fā)表于 10-12 10:43 ?1913次閱讀

    Python中的十個(gè)安全陷阱(一)

    Python 開發(fā)者們在使用標(biāo)準(zhǔn)庫和通用框架時(shí),都以為自己的程序具有可靠的安全性。然而,在 Python 中,就像在任何其它編程語言中一樣,有一些特性可能會(huì)被開發(fā)者們誤解或誤用。通常而言,只有極少的微妙之處或細(xì)節(jié)會(huì)使開發(fā)者們疏忽
    的頭像 發(fā)表于 03-24 16:42 ?1267次閱讀

    如何在Raspberry Pi項(xiàng)目中添加Siri控制

    目的:本教程旨在教您如何使用SiriControl開源Python框架在RaspberryPi項(xiàng)目中添加Siri功能和控制功能。
    的頭像 發(fā)表于 02-27 10:27 ?724次閱讀
    如何在Raspberry Pi<b class='flag-5'>項(xiàng)目中</b>添加Siri控制

    這17種焊接陷阱,你遇到過多少?

    良好的焊接是保證電路穩(wěn)定持久工作的前提。下面給出了常見到的焊接缺陷??纯茨?b class='flag-5'>遇到過多少種?焊接中的常見問題▲陷阱1:錫珠▲陷阱2:擾動(dòng)的焊接——在焊接點(diǎn)冷卻過程中焊錫移動(dòng),造成焊接表面起霧、結(jié)晶、粗糙
    的頭像 發(fā)表于 04-14 09:39 ?826次閱讀
    這17種焊接<b class='flag-5'>陷阱</b>,你<b class='flag-5'>遇到</b>過多少?

    這17種焊接陷阱,你遇到過多少?

    良好的焊接是保證電路穩(wěn)定持久工作的前提。下面給出了常見到的焊接缺陷。看看你遇到過多少種?焊接中的常見問題▲陷阱1:錫珠▲陷阱2:擾動(dòng)的焊接——在焊接點(diǎn)冷卻過程中焊錫移動(dòng),造成焊接表面起霧、結(jié)晶、粗糙
    的頭像 發(fā)表于 04-14 09:37 ?759次閱讀
    這17種焊接<b class='flag-5'>陷阱</b>,你<b class='flag-5'>遇到</b>過多少?

    如何在Python項(xiàng)目中應(yīng)用分層架構(gòu)

    本文來自一位 Python 開發(fā)者對一個(gè)龐大的 Python 項(xiàng)目的代碼結(jié)構(gòu)的總結(jié)。
    發(fā)表于 08-17 10:48 ?1010次閱讀
    如何在<b class='flag-5'>Python</b><b class='flag-5'>項(xiàng)目中</b>應(yīng)用分層架構(gòu)