開放API網關實踐(二) —— 重放攻擊及防護

如何設計實現一個輕量的開放API網關之重放攻擊及防護java

文章地址: blog.piaoruiqing.com/2019/08/11/…react

前言

上一篇文章《開放API網關實踐(一)》中的接口設計提到timestampnonce兩個參數的做用是用來防重放. 本文就重放攻擊及其防護進行探討. 先拋出兩個問題:api

  • 什麼是重放攻擊
  • 如何防護重放攻擊

什麼是重放攻擊(Replay Attacks)

什麼是重放, 先舉個例子:瀏覽器

打開瀏覽器的調試工具並訪問一個網站, 在網絡工具中找到一個請求並右鍵選擇Replay. 如圖:緩存

Chrome請求重放

上述的重放操做是接口調試中比較經常使用的手段, 這種操做可讓咱們跳過認證信息的生成過程, 直接重複發起屢次有效的請求.安全

重放攻擊是一種黑客經常使用的攻擊手段, 又稱重播攻擊回放攻擊, 是指攻擊者發送目的主機已接收過的數據, 以達到欺騙系統的目的, 主要用於身份認證過程, 破壞認證的正確性.服務器

舉個易懂的例子:markdown

  • 服務端提供了打款接口, 用戶A向服務端請求發起一次打款5元的操做(附帶了簽名並進行了加密), 服務端接收到了數據並正確打款給用戶B.
  • 但這個請求被黑客攔截到(可能就是用戶B乾的 ( ̄▽ ̄)"), 黑客將請求原封不動地向服務器發送, 服務器屢次錯誤地打款給用戶B. (固然, 這些都是是創建在服務端的付款沒作冪等等防範措施、安全級別較低的前提下)
  • 儘管A發起的請求有簽名和加密, 但B無需破解這個數據, 只是將一樣的數據重複發給服務器就能達到欺騙的目的.

重放攻擊

模擬重放攻擊

實驗器材

序號 名稱 數量 備註
1 服務器 2 10.33.30.101 - 真實服務器
10.33.30.100 - 僞造服務器
2 域名 1 replay-test.piaoruiqing.com (10.33.30.101)
3 DNS服務器 1 用來模擬DNS劫持

實驗步驟

  1. 啓動服務器, 請求接口並收到響應數據.
  2. 劫持DNS(在路由器中修改DNS服務器地址模擬劫持), 並攔截請求數據.
  3. 向服務器重複發送攔截到的數據(重放攻擊).

過程記錄

準備工做

DNS配置, 將域名replay-test.piaoruiqing.com指向內網中服務器的IP. 並啓動服務器.網絡

DNS

正常請求

使用postman發起一個正常的請求, 其中籤名已在Pre-request-script中生成.app

預處理請求

經過DNS劫持來攔截數據

修改內網的dnsmasq配置, 將域名replay-test.piaoruiqing.com指向僞造的服務器10.33.30.100.

DNS劫持

DNS劫持

此時向replay-test.piaoruiqing.com發起的請求便會被髮送到僞造的服務器上(10.33.30.100), 手動將請求的數據保存下來. 因爲請求帶有簽名, 且攻擊者並無拿到私鑰, 故沒法篡改請求, 但能夠進行重放攻擊. 如圖, 僞造服務器已成功接收到請求數據:

攔截數據

[版權聲明]
本文發佈於 樸瑞卿的博客, 容許非商業用途轉載, 但轉載必須保留原做者 樸瑞卿 及連接: blog.piaoruiqing.com. 若有受權方面的協商或合做, 請聯繫郵箱: piaoruiqing@gmail.com.

重放請求

使用上一步保存下來的數據, 直接向真實服務器發送請求(帶有簽名數據). 如圖:

重放

事實上, 簽名、加密等手段並不能防護重放攻擊, 由於攻擊者攔截到的數據已經是正確的請求數據, 即便沒法破解其內容, 也能夠重放向服務器發送原數據以達到欺騙的目的.

如何防護重放攻擊

百度百科

  1. 加隨機數: 該方法優勢是認證雙方不須要時間同步,雙方記住使用過的隨機數, 如發現報文中有之前使用過的隨機數, 就認爲是重放攻擊. 缺點是須要額外保存使用過的隨機數, 若記錄的時間段較長, 則保存和查詢的開銷較大.

  2. 加時間戳: 該方法優勢是不用額外保存其餘信息. 缺點是認證雙方須要準確的時間同步, 同步越好, 受攻擊的可能性就越小. 但當系統很龐大, 跨越的區域較廣時, 要作到精確的時間同步並非很容易.

  3. 加流水號: 就是雙方在報文中添加一個逐步遞增的整數, 只要接收到一個不連續的流水號報文(太大或過小), 就認定有重放威脅. 該方法優勢是不須要時間同步, 保存的信息量比隨機數方式小. 缺點是一旦攻擊者對報文解密成功, 就能夠得到流水號, 從而每次將流水號遞增欺騙認證端.

在實際使用中, 常將1和2結合使用, 時間戳有效期內判斷隨機數是否已存在, 有效期外則直接丟棄.

重放攻擊防護實踐

咱們採起時間戳+隨機數的方式來實現一個簡單的重放攻擊攔截器. 時間戳和隨機數互補, 既能在時間有效範圍內經過校驗緩存中的隨機數是否存在來分辨是否爲重放請求, 也能在緩存失效後(緩存有效時間和時間範圍一致)經過時間戳來校驗該請求是否爲重放. 如圖:

重放攻擊防護

代碼以下:

@Resource
private ReactiveStringRedisTemplate reactiveStringRedisTemplate;

private ReactiveValueOperations<String, String> reactiveValueOperations;

@PostConstruct
public void postConstruct() {
    reactiveValueOperations = reactiveStringRedisTemplate.opsForValue();
}

@Override
protected Mono<Void> doFilter(ServerWebExchange exchange, WebFilterChain chain) {
    // 此處的`ATTRIBUTE_OPEN_API_REQUEST_BODY`是前面過濾器存入的
    OpenApiRequest<String> body 
        = exchange.getRequiredAttribute(ATTRIBUTE_OPEN_API_REQUEST_BODY);
    if (!ObjectUtils.allNotNull(body, body.getTimestamp(), body.getNonce())) {
        return fail(exchange);
    }
    Long gmt = System.currentTimeMillis();
    // (一)
    if (gmt + effectiveTimeRange < body.getTimestamp() || 
        gmt - effectiveTimeRange > body.getTimestamp()) {
        return fail(exchange);
    }
    // (二)
    return reactiveValueOperations.setIfAbsent(MessageFormat.format(
            KEY_REPLAY_NONCE, body.getAppId(), body.getNonce()),
            String.valueOf(System.currentTimeMillis()),
            Duration.ofMillis(effectiveTimeRange * 2L))
        .log(LOGGER, Level.FINE, true)
        .flatMap(approved -> approved ? 
                 chain.filter(exchange) : fail(FORBIDDEN, exchange)
            );

複製代碼
  • (一): 請求時間超出時間範圍的將被拒絕.
  • (二): 緩存過時時間等於有效時間的跨度, 若緩存中已存在該隨機數, 則拒絕.

結語

重放攻擊防護的關鍵點:

  • 記錄請求標識並緩存, 接受請求時校驗, 拒絕重放, 即將nonce存入緩存, 拒絕相同的nonce
  • 隨機數的方式可能形成過多的緩存, 故須要配合時間戳進行過濾, 時間戳不在有效範圍內的一概拒絕.

重放攻擊是一種經常使用且有效的攻擊手段, 其危害不可忽視, 儘管能夠經過業務層面來保障數據的正確性, 但依舊會給系統形成沒必要要開銷, 在網關層過濾掉重放請求是一個不錯的選擇.

若是這篇文章對您有幫助,請點個贊吧 ( ̄▽ ̄)"

系列文章:

歡迎關注公衆號:

[版權聲明]
本文發佈於 樸瑞卿的博客, 容許非商業用途轉載, 但轉載必須保留原做者 樸瑞卿 及連接: blog.piaoruiqing.com. 若有受權方面的協商或合做, 請聯繫郵箱: piaoruiqing@gmail.com.
相關文章
相關標籤/搜索