安全圈 | 专注于最新网络信息安全讯息新闻

首页

python中編碼二三事

作者 rampino 时间 2020-02-24
all

在稽核的時候比較喜歡注意對字串操作的編碼、解碼和截這些操作,因為這裡有可能導致對抗SQLi和XSS等安全函數失效。

前兩天改一個自己剛入學的時候寫的python小工具,發現編碼解碼真是一個頭疼卻有不得不面對的問題。

一個小工具如果是自己用,寫的很粗獷能達到預期目的就行。但是如果給別人用甚至更多人用,就不得不考慮程式碼的健壯了,不僅僅要預想運行的不同環境,也要考慮不符合預期的輸入應該怎麼處理。

0x01

從檔案或者資料庫讀取輸入後,在對內容進行處理前(如正則匹配),要先對輸入進行一次規範化。我發現這是我經常疏忽的問題,結果就是在我的機器上可以跑,而給別人用的時候總會出問題。

一個數據互動不大的程式,可以考慮直接讀寫檔案txt/csv/xls等,再大一點SQLite也不錯。從檔案讀取的內容的編碼和檔案是一致的,這時候如果要取出來的字串進行正則匹配或者去資料庫匹配結果,編碼就很重要了。

可以考慮使用chardet模塊先對字串編碼格式化,再進行其他處理。ab是從兩種不同的檔案中讀取到的字串,cd是程式中定義的字串,下圖可以看到chardect對他們的編碼的識別。

從c和d的編碼的區別我們可以發現,變數的值如果是一般字元,變數的編碼格式是ascii;變數的值如果是漢字或者其他特殊文字,將隨py檔案的編碼而編碼。

大多數資料中提到這種情況會隨檔案也就是第二行聲明的utf8而編碼(事實上確實如果在頭部不申明編碼,這樣進行賦值程式將會報錯)。然而測試發現即使檔案申明用gbk編碼,值為漢字的變數的編碼格式仍然是utf8,這可能和作業系統有關,沒有繼續研究這個點,因為既然識別出來了,可以用chardet.detect()很方便的解出來。囙此只要在操作字串之前加上

這時候字串被轉換成ascii格式,這種格式可以使用encode函數轉換成想要的編碼就行了。

更多的時候我們會使用SQLite或者MySQL,比如做資料對比或者選取關鍵資訊時,不編碼肯定會出問題,MySQL資料存儲的時候我一般設定成utf8-general-ci,所以設定資料庫連接的時候使用一樣的格式。

這樣設定一致讀出來的數據直接處理一般沒出什麼問題,然而養成好習慣還是可以用chardet先格式化一次避免出現問題。

0x02

剩下聊一些其他不符合預期的輸入或者操作導致的問題的解决吧。

使用try,然後pass掉出錯的數據自然是一個很省力的方案。但常常不是最優的方案,因為這樣本來能够處理的數據因為上面的原因而被拋弃掉,如果捨棄數量大或者剛好捨棄掉重要的數據對功能產生很大影響。所以最好還是要找到根源問題所在,上面的小程式改的心有些累,就是因為有時候有少量資料處理中會出錯,不好被直接pass掉而不得不重新選取方法,導致了需要修改大片的程式碼~

找到問題->查找資料->思考解決方案->解决問題這個鏈條中,我們常會比較在意的是找第一個和最後一個環節,現在感覺中間的反復資料查找和思考卻是最難的。上文提到的程式修改的時候還遇到了很多各種各樣的問題,git一些項目中的做法和stackoverflow上的討論等等常能提供很多思路。

具體做法還是見人見智,找到適合自己的管道就好。Leader Ourren常讓我們在各方面要多自己思考,而不要去依賴別人給出的解決方案。事實上也切身感受到,如果在過程中自己多思考,最後常會發現解决問題的方法上得到的收穫遠大於問題本身。

The last,wish us to have a good job in the Sep’s hard winter.

< 手把手教你DIY一個DNS/HTTP帶外査詢工具

PHP序列化學習總結 >