1. 程式人生 > >Python中的一個糟糕的Web應用程式

Python中的一個糟糕的Web應用程式

一、不安全的Web程式示例。

下面展示一個不安全的Web應用程式。

這個程式碼採用了Flask框架,但是不安全的原因不是因為使用了Flask。

Python中的一個糟糕的Web應用程式

 

上面的程式碼很危險,無法抵禦現在Web上諸多向量的重要攻擊。

先引入上述程式碼中出現的四個模板。

更多Python視訊、原始碼、資料加群960410445免費獲取

 

1.base.html頁面的Jinja模板

Python中的一個糟糕的Web應用程式

 

這段程式碼中出現了value值,第一次顯示該介面時,初始的value的值就會顯示在可編輯文字框中。

2.login.html的Jinja2模板

Python中的一個糟糕的Web應用程式

 

如果使用者輸入了錯誤的密碼,使用者重新輸入時就可以不用再次輸入他們的使用者名稱。

3.index.html的Jinja2模板

Python中的一個糟糕的Web應用程式

 

很多情況下,使用者會經常輸入錯誤的表單資訊。因此這段程式碼會檢測是否接收到了complaint字串。如果有的話,就顯示在表單的頂部。這段程式碼冗餘度比較高。如果表單資訊有誤且需要重新顯示的話。就需要有三個表單欄位,並且要使用使用者試圖提交時來實現填充這三個欄位。

4.pay.html中的Jiaja2模板

Python中的一個糟糕的Web應用程式

 

在設計網站時,最好在每個提交按鈕旁邊都提供取消功能。但是取消功能的元素要比預設的表單提交按鈕小很多。這樣子使用者操作失誤將會降到最低。

二、下面說一下表單和HTTP方法。

HTML表單的預設action是GET。它可以只包含一個文字框。

進行GET的表單會把輸入的欄位直接放入URL中,然後將其作為HTTP請求的路徑。

這將意味著GET的引數將成為瀏覽歷史的一部分。所以絕對不能用GET來傳輸密碼或者證書這樣的敏感資訊。

另外一種表單(POST,PUT和DELETE的表單)在URL中絕對不會包含任何表單資訊。表單資訊也不會出現在HTTP請求的路徑中。

瀏覽器會把所有資料都放入請求訊息體中,而請求的路徑本身是沒有變化的。

Web瀏覽器知道POST是一個可能會造成狀態變化的操作。所以在處理POST請求時候都會很小心。如果使用者在瀏覽一個有POST請求返回的頁面時重新載入網頁,那麼瀏覽器將會彈出一個對話方塊。一般都會輸出一個警告。

重複提交表單的後果是非常嚴重的。

為了防治重新載入,或者在前進、後退的時候不斷收到瀏覽器的對話方塊。有兩種技術可以供網站採用。

  • 使用JavaScript或者HTML5表單的輸入限制來嘗試實現防止使用者提交含有非法值的表單。在符合要求之前禁用提交按鈕。或者使用JavaScript在不需要重新載入頁面的情況下提交整個表單並獲取響應。
  • 當表單已經正確提交併且成功執行了POST請求的動作之後,Web應用程式不應該返回已經完成的200 OK介面。而是立即進行一個GET請求,立刻轉到GET請求要訪問的介面。

三、安全的cookie和不安全的cookie。

上述的程式碼中試圖保護使用者的隱私。必須登入成功後才能通過“/”的GET請求檢視賬單列表。如果想通過POST請求來進行支付。使用者必須成功登陸。

但是在登陸之後,伺服器的相應資訊會包含一個名稱為username的cookie,並且初始值已經被設定為badguy。顯然,後續只要包含這個cookie,那麼網站就會認為傳送這些請求的使用者已經輸入了正確的使用者名稱和密碼。

這個時候很不安全,我們可以偽造cookie。只需要賬單系統中的另外一個已經登陸的使用者,我們就可以用偽造請求。

因此要保證無法被偽造,有3種安全的方法。

  • 保留可讀性,利用數字簽名對cookie簽名。這樣子他們可以偽造cookie,但是無法偽造簽名。所以網站不會信任他們重新構造的cookie。
  • 對cookie進行完全加密。使用者無法讀懂,可能計算機也無法解析。
  • 可以使用一個純隨機的字串作為cookie。將這些字串存在自己的資料庫中。每個使用者對應一個隨機的字串。如果是使用者的HTTP可能被轉發到多臺不同的伺服器,那麼所有的伺服器都要能夠訪問這一個持久化的session儲存。有一些儲存到核心資料庫中。有一些程式使用Redis例項或者其他儲存器較短的方式,以防止核心資料庫的查詢負載過高。

四、非持久型跨站指令碼。

惡意使用者無法竊取或者偽造cookie,也就無法瀏覽器或者Python程式偽裝成另外一個使用者。

如果他們可以控制另外一個已經登入使用者的瀏覽器,就不需要檢視cookie,而直接通過瀏覽器的請求,請求中就會自動包含正確的cookie。

第一種是非持久型的跨站指令碼(XSS)。攻擊者將會自己的指令碼插入網站,網站把這些腳本當作自己的指令碼使用。比如攻擊者想要向他們的賬戶支付110美元。可以寫如下的程式碼:

Python中的一個糟糕的Web應用程式

 

攻擊者將這段包含JavaScript指令碼的HTML注入頁面。

攻擊者只需要偽造一個入口,誘使使用者看到並點選設計好的URL。

為了防止被使用者發現,經常會分享一個短連結,只有使用者點選之後,短連線才會擴充套件成為包含跨站指令碼的原始完整連結。

五、持久型跨站指令碼。

如果攻擊者無法再一個又長又醜的URL中設定陷阱。那就必須用其他的方法注入JavaScript。掃視了一遍主頁,他們可能會在顯示賬單的Memo欄位中做手腳。

當然,要在頁面上顯示精心設計的Memo要比直接將Memo嵌入URL中會複雜一些。而且攻擊者是可以直接將URL匿名提供給使用者的。要在頁面上顯示Memo,就必須使用虛假的個人資訊註冊網站。或者利用另一個使用者的賬戶向受害者進行一個支付,並且在Memo欄位中包含<script>元素以及上面的那一段JavaScript指令碼。

每次訪問首頁時,都會因為執行指令碼而支出一筆賬單。

持久型跨站指令碼攻擊,只要受害者訪問了網站,JavaScript指令碼就會不斷的隱式執行。直到伺服器上的資料都被清空。

上述程式碼,之所以無法抵禦這一型別的攻擊。是因為Jinja2的開發者沒有理解Jinja2的使用方法。它並不會自動進行任何轉義。

六、跨站請求偽造。

當我們對所有內容進行轉義,不用再擔心XSS攻擊。

但是他們可以從另外一個完全不同的網站提交表單。

這裡不再展開介紹。感興趣的同學可以查一下相關的資料。

由於使用者的瀏覽器啟用了JavaScript,攻擊者可以直接把程式碼中的<script>元素插入使用者要載入的頁面、論壇帖子或者評論中。然後坐等受害者的錢流入他們的賬戶。

如何解決這個問題呢?

我們可以通過增加構造以及提交表單的難度。比如表單中增加一個額外的欄位,其中包含只對表單的合法使用者或者合法使用者的瀏覽器私鑰。這樣攻擊者也就無法為造出伺服器信任的POST請求。

七、改進的應用程式。

下面是改進後的程式。

Python中的一個糟糕的Web應用程式

 

一個程式想要完全沒有安全漏洞是困難的。只能儘可能的避免。

Python中的一個糟糕的Web應用程式