RESTFUL API 安全設計指南

wyzsk發表於2020-08-19
作者: xxlegend · 2015/10/18 15:08

0x01 REST API 簡介


REST的全稱是REpresentational State Transfer,表示表述性無狀態傳輸,無需session,所以每次請求都得帶上身份認證資訊。rest是基於http協議的,也是無狀態的。只是一種架構方式,所以它的安全特性都需我們自己實現,沒有現成的。建議所有的請求都透過https協議傳送。RESTful web services 概念的核心就是“資源”。 資源可以用 URI 來表示。客戶端使用 HTTP 協議定義的方法來傳送請求到這些 URIs,當然可能會導致這些被訪問的”資源“狀態的改變。HTTP請求對應關係如下:

==========  =====================  ========================
HTTP 方法   行為                   示例
==========  =====================  ========================
GET         獲取資源的資訊         http://xx.com/api/orders
GET         獲取某個特定資源的資訊 http://xx.com/api/orders/123
POST        建立新資源             http://xx.com/api/orders
PUT         更新資源               http://xx.com/api/orders/123
DELETE      刪除資源               http://xx.com/api/orders/123
==========  ====================== =======================

對於請求的資料一般用json或者xml形式來表示,推薦使用json。

0x02 身份認證


身份認證包含很多種,有HTTP Basic,HTTP Digest,API KEY,Oauth,JWK等方式,下面簡單講解下:

2.1 HTTP Basic

REST由於是無狀態的傳輸,所以每一次請求都得帶上身份認證資訊,身份認證的方式,身份認證的方式有很多種,第一種便是http basic,這種方式在客戶端要求簡單,在服務端實現也非常簡單,只需簡單配置apache等web伺服器即可實現,所以對於簡單的服務來說還是挺方便的。但是這種方式安全性較低,就是簡單的將使用者名稱和密碼base64編碼放到header中。

base64編碼前:Basic admin:admin
base64編碼後:Basic YWRtaW46YWRtaW4=
放到Header中:Authorization: Basic YWRtaW46YWRtaW4=

正是因為是簡單的base64編碼儲存,切記切記在這種方式下一定得注意使用ssl,不然就是裸奔了。

在某些產品中也是基於這種類似方式,只是沒有使用apache的basic機制,而是自己寫了認證框架,原理還是一樣的,在一次請求中base64解碼Authorization欄位,再和認證資訊做校驗。很顯然這種方式有問題,認證資訊相當於明文傳輸,另外也沒有防暴力破解功能。

2.2 API KEY

API Key就是經過使用者身份認證之後服務端給客戶端分配一個API Key,類似:http://example.com/api?key=dfkaj134,一般的處理流程如下:

一個簡單的設計示例如下:

client端:

clint端

server端:

server端

client端向服務端註冊,服務端給客戶端傳送響應的api_key以及security_key,注意儲存不要洩露,然後客戶端根據api_key,secrity_key,timestrap,rest_uri採用hmacsha256演算法得到一個hash值sign,構造途中的url傳送給服務端。

服務端收到該請求後,首先驗證api_key,是否存在,存在則獲取該api_key的security_key,接著驗證timestrap是否超過時間限制,可依據系統成而定,這樣就防止了部分重放攻擊,途中的rest_api是從url獲取的為/rest/v1/interface/eth0,最後計算sign值,完之後和url中的sign值做校驗。這樣的設計就防止了資料被篡改。

透過這種API Key的設計方式加了時間戳防止了部分重放,加了校驗,防止了資料被篡改,同時避免了傳輸使用者名稱和密碼,當然了也會有一定的開銷。

2.3 Oauth1.0a或者Oauth2

OAuth協議適用於為外部應用授權訪問本站資源的情況。其中的加密機制與HTTP Digest身份認證相比,安全性更高。使用和配置都比較複雜,這裡就不涉及了。

2.4 JWT

JWT 是JSON Web Token,用於傳送可透過數字簽名和認證的東西,它包含一個緊湊的,URL安全的JSON物件,服務端可透過解析該值來驗證是否有操作許可權,是否過期等安全性檢查。由於其緊湊的特點,可放在url中或者 HTTP Authorization頭中,具體的演算法就如下圖

jwt組成圖

0x03 授權


身份認證之後就是授權,根據不同的身份,授予不同的訪問許可權。比如admin使用者,普通使用者,auditor使用者都是不同的身份。簡單的示例:

#!php
$roles = array(
'ADMIN'=>array(
'permit'=>array('/^((\/system\/(clouds|device)$/'), // 允許訪問哪些URL的正規表示式
'deny'=>array('/^(\/system\/audit)$/') // 禁止訪問哪些URL的正規表示式
),
'AUDIT'=>array(
'permit'=>array('/^(\/system\/audit)$/'),//允許訪問的URL正規表示式
'deny'=>array('/^((\/system\/(clouds|device).*)$/')
)
);

上述是垂直許可權的處理,如果遇到了平行許可權的問題,如使用者A獲取使用者B的身份資訊或者更改其他使用者資訊,對於這些敏感資料介面都需要加上對使用者的判斷,這一步一般都在具體的邏輯實現中實現。

0x04 URL過濾

在進入邏輯處理之前,加入對URL的引數過濾,如/site/{num}/policy 限定num位置為整數等,如果不是引數則直接返回非法引數,設定一個url清單,不在不在url清單中的請求直接拒絕,這樣能防止開發中的api洩露。rest api介面一般會用到GET,POST,PUT,DELETE,未實現的方法則直接返回方法不允許,對於POST,PUT方法的資料採用json格式,並且在進入邏輯前驗證是否json,不合法返回json格式錯誤。

0x05 重要功能加密傳輸

第一步推薦SSL加密傳輸,同時對於系統中重要的功能做加密傳輸,如證照,一些資料,配置的備份功能,同時還得確保具備相應的許可權,這一步會在授權中涉及。

0x06 速率限制

請求速率限制,根據api_key或者使用者來判斷某段時間的請求次數,將該資料更新到記憶體資料庫(redis,memcached),達到最大數即不接受該使用者的請求,同時這樣還可以利用到記憶體資料庫key在特定時間自動過期的特性。在php中可以使用APC,Alternative PHP Cache (APC) 是一個開放自由的PHP opcode 快取。它的目標是提供一個自由、 開放,和健全的框架用於快取和最佳化PHP的中間程式碼。在返回時設定X-Rate-Limit-Reset:當前時間段剩餘秒數,APC的示例程式碼如下:

#!php
Route::filter('api.limit', function()
{
$key = sprintf('api:%s', Auth::user()->api_key);
// Create the key if it doesn't exist
Cache::add($key, 0, 60);
// Increment by 1
$count = Cache::increment($key);
// Fail if hourly requests exceeded
if ($count > Config::get('api.requests_per_hour'))
{
App::abort(403, 'Hourly request limit exceeded');
}
});

0x07 錯誤處理


對於非法的,導致系統出錯的等請求都進行記錄,一些重要的操作,如登入,註冊等都透過日誌介面輸出展示。有一個統一的出錯介面,對於400系列和500系列的錯誤都有相應的錯誤碼和相關訊息提示,如401:未授權;403:已經鑑權,但是沒有相應許可權。如不識別的url:{"result":"Invalid URL!"},錯誤的請求引數{"result":"json format error"},不允許的方法:{"result":"Method Not Allowed"},非法引數等。上面所說的都是單狀態碼,同時還有多狀態碼,表示部分成功,部分字元非法等。示例如下:

HTTP/1.1 207 Multi-Status
Content-Type: application/json; charset="UTF-8"
Content-Length: XXXX    

{
"OPT_STATUS": 207
"DATA": {
    "IP_ADDRESS": [{
        "INTERFACE": "eth0",
        "IP_LIST":[{
             "IP": "192.168.1.1",
             "MASK": "255.255.0.0",
"MULTI_STATUS": 200,
             "MULTI_RESULT": "created successfully"
        },{
             "IP": "192.167.1.1",
             "MASK": "255.255.0.0",
"MULTI_STATUS": 409,
             "MULTI_RESULT": "invalid parameter"
}]
}]
},

0x08 重要ID不透明處理


在系統一些敏感功能上,比如/user/1123 可獲取id=1123使用者的資訊,為了防止字典遍歷攻擊,可對id進行url62或者uuid處理,這樣處理的id是唯一的,並且還是字元安全的。

0x09 其他注意事項


(1)請求資料,對於POST,DELETE方法中的資料都採用json格式,當然不是說rest架構不支援xml,由於xml太不好解析,對於大部分的應用json已經足夠,近一些的趨勢也是json越來越流行,並且json格式也不會有xml的一些安全問題,如xxe。使用json格式目前能防止掃描器自動掃描。

(2)返回資料統一編碼格式,統一返回型別,如Content-Type: application/json; charset="UTF-8"

(3)在邏輯實現中,json解碼之後進行引數驗證或者轉義操作,第一步json格式驗證,第二步具體引數驗證基本上能防止大部分的注入問題了。

(4)在傳輸過程中,採用SSL保證傳輸安全。

(5)儲存安全,重要資訊加密儲存,如認證資訊hash儲存。

總之,儘量使用SSL。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章