防止重放機(jī)制

一皆疹、API重放攻擊

我們在設(shè)計接口的時候,最怕一個接口被用戶截取用于重放攻擊抵知。重放攻擊是什么呢墙基?就是把你的請求原封不動地再發(fā)送一次,兩次...n次刷喜,重放攻擊是二次請求残制,黑客通過抓包獲取到了請求的HTTP報文,然后黑客自己編寫了一個類似的HTTP請求掖疮,發(fā)送給服務(wù)器初茶。也就是說服務(wù)器處理了兩個請求,先處理了正常的HTTP請求浊闪,然后又處理了黑客發(fā)送的篡改過的HTTP請求恼布。

如果這個正常邏輯是插入數(shù)據(jù)庫操作,那么一旦插入數(shù)據(jù)庫的語句寫的不好搁宾,就有可能出現(xiàn)多條重復(fù)的數(shù)據(jù)折汞。一旦是比較慢的查詢操作,就可能導(dǎo)致數(shù)據(jù)庫堵住等情況盖腿。

1.1 重放攻擊的概念:

重放攻擊是計算機(jī)世界黑客常用的攻擊方式之一爽待,所謂重放攻擊就是攻擊者發(fā)送一個目的主機(jī)已接收過的包,來達(dá)到欺騙系統(tǒng)的目的翩腐,主要用于身份認(rèn)證過程鸟款。

二、重放攻擊的防御方案

2.1 基于timestamp方案

每次HTTP請求茂卦,都需要加上timestamp參數(shù)何什,然后把timestamp和其他參數(shù)一起進(jìn)行數(shù)字簽名。因為一次正常的HTTP請求等龙,從發(fā)出到達(dá)服務(wù)器一般都不會超過60s处渣,所以服務(wù)器收到HTTP請求之后伶贰,首先判斷時間戳參數(shù)與當(dāng)前時間相比較,是否超過了60s霍比,如果超過了則認(rèn)為是非法的請求幕袱。

假如黑客通過抓包得到了我們的請求url:
http://www.reibang.com?uid=3535353535353535&time=1543991604448&sign=eaba21f90e635c22d2d775731ec03a92
其中

long uid = 3535353535353535L;
String token = "fewgjiwghwoi3ji4oiwjo34ir4erojwk";
long time = new Date().getTime();//1543991604448
String sign = MD5Utils.MD5Encode("uid=" + uid + "&time=" + time + token,"utf8");
public class MD5Utils {
    private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

    /**
     * MD5加密
     * @param origin 字符
     * @param charsetname 編碼
     * @return
     */
    public static String MD5Encode(String origin, String charsetname){
        String resultString = null;
        try{
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if(null == charsetname || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        }catch (Exception e){
        }
        return resultString;
    }


    public static String byteArrayToHexString(byte b[]){
        StringBuffer resultSb = new StringBuffer();
        for(int i = 0; i < b.length; i++){
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    public static String byteToHexString(byte b){
        int n = b;
        if(n < 0){
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigIts[d1] + hexDigIts[d2];
    }
}

一般情況下暴备,黑客從抓包重放請求耗時遠(yuǎn)遠(yuǎn)超過了60s悠瞬,所以此時請求中的time參數(shù)已經(jīng)失效了。

如果黑客修改time參數(shù)為當(dāng)前的時間戳涯捻,則sign參數(shù)對應(yīng)的數(shù)字簽名就會失效浅妆,因為黑客不知道token值,沒有辦法生成新的數(shù)字簽名障癌。

但這種方式的漏洞也是顯而易見的凌外,如果在60s之內(nèi)進(jìn)行重放攻擊,那就沒辦法了涛浙,所以這種方式不能保證請求僅一次有效康辑。

2.2 基于nonce方案

nonce是僅一次有效的隨機(jī)字符串,要求每次請求時轿亮,該參數(shù)要保證不同疮薇,所以該參數(shù)一般與時間戳有關(guān),我們這里為了方便起見我注,直接使用時間戳作為種子按咒,隨機(jī)生成16位的字符串,作為nonce參數(shù)但骨。

我們將每次請求的nonce參數(shù)存儲到一個redis中励七。 每次處理HTTP請求時,首先判斷該請求的nonce參數(shù)是否在redis中奔缠,如果存在則認(rèn)為是非法請求掠抬。

假如黑客通過抓包得到了我們的請求url:
http://www.reibang.com?uid=3535353535353535&nonce=RLLUammMSInlrNWb&sign=d2f7406dfdeea3561f753d9e0d1dc320

long uid = 3535353535353535L;
String token = "fewgjiwghwoi3ji4oiwjo34ir4erojwk";
long time = new Date().getTime();//1543993280840
String nonce = RandomUtils.getRandomChar(time);
String sign = MD5Utils.MD5Encode("uid=" + uid + "&nonce=" + nonce + token,"utf8");
public class RandomUtils {

    public static String getRandomChar(long time){
        Random random = new Random(time);
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < 16; i++){
            char c = (char)(random.nextLong() % 26 + 97);
            sb.append(c);
        }
        return sb.toString();
    }
}

nonce參數(shù)在首次請求時,已經(jīng)被存儲到了服務(wù)器上的redis中校哎,再次發(fā)送請求會被識別并拒絕两波。
nonce參數(shù)作為數(shù)字簽名的一部分,是無法篡改的贬蛙,因為黑客不清楚token雨女,所以不能生成新的sign。

這種方式也有很大的問題阳准,那就是存儲nonce的redis會越來越大氛堕,驗證nonce是否存在redis中的耗時會越來越長。我們不能讓nonce集合無限大野蝇,所以需要定期清理該“集合”讼稚,但是一旦該集合被清理括儒,我們就無法驗證被清理了的nonce參數(shù)了。也就是說锐想,假設(shè)該集合平均1天清理一次的話帮寻,我們抓取到的該url,雖然當(dāng)時無法進(jìn)行重放攻擊赠摇,但是我們還是可以每隔一天進(jìn)行一次重放攻擊的固逗。而且存儲24小時內(nèi),所有請求的“nonce”參數(shù)藕帜,也是一筆不小的開銷烫罩。

2.2 基于timestamp+nonce方案

我們常用的防止重放的機(jī)制是使用timestamp和nonce來做的重放機(jī)制。

每個請求帶的時間戳不能和當(dāng)前時間超過一定規(guī)定的時間(60s)洽故。這樣請求即使被截取了贝攒,你也只能在60s內(nèi)進(jìn)行重放攻擊,過期失效时甚。
但是攻擊者還有60s的時間攻擊隘弊。所以我們就需要加上一個nonce隨機(jī)數(shù),防止60s內(nèi)出現(xiàn)重復(fù)請求荒适。

timstamp參數(shù)對于超過60s的請求梨熙,都認(rèn)為非法請求;
redis存儲60s內(nèi)的nonce參數(shù)的集合吻贿,60s內(nèi)重復(fù)則認(rèn)為是非法請求串结。

http://www.reibang.com?uid=3535353535353535&time=1543993979284&nonce=VUmVZgKxkpk_rabQ&sign=da5dba49e4211df48bb5b619358c0db0

long uid = 3535353535353535L;
String token = "fewgjiwghwoi3ji4oiwjo34ir4erojwk";
long time = new Date().getTime();//1543993979284
String nonce = RandomUtils.getRandomChar(time);
String sign = MD5Utils.MD5Encode("uid=" + uid + "&time" + time +"&nonce=" + nonce + token,"utf8");

三、服務(wù)端實現(xiàn)流程

服務(wù)端第一次在接收到這個nonce的時候做下面行為:
1 去redis中查找是否有key為nonce:{nonce}的string
2 如果沒有舅列,則創(chuàng)建這個key肌割,把這個key失效的時間和驗證time失效的時間一致,比如是60s帐要。
3 如果有把敞,說明這個key在60s內(nèi)已經(jīng)被使用了,那么這個請求就可以判斷為重放請求榨惠。

3.1 示例

那么比如奋早,下面這個請求:

http://www.reibang.com?uid=3535353535353535&time=1543993979284&nonce=VUmVZgKxkpk_rabQ&sign=da5dba49e4211df48bb5b619358c0db0

time,nonce赠橙,sign都是為了簽名和防重放使用耽装。

time是發(fā)送接口的時間,nonce是隨機(jī)串期揪,sign是對uid掉奄,time,nonce。簽名的方法可以是md5({秘要}key1=val1&key2=val2&key3=val3...)

服務(wù)端接到這個請求:
1 先驗證sign簽名是否合理凤薛,證明請求參數(shù)沒有被中途篡改
2 再驗證time是否過期姓建,證明請求是在最近60s被發(fā)出的
3 最后驗證nonce是否已經(jīng)有了诞仓,證明這個請求不是60s內(nèi)的重放請求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市速兔,隨后出現(xiàn)的幾起案子墅拭,更是在濱河造成了極大的恐慌,老刑警劉巖涣狗,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谍婉,死亡現(xiàn)場離奇詭異,居然都是意外死亡屑柔,警方通過查閱死者的電腦和手機(jī)屡萤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門珍剑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掸宛,“玉大人,你說我怎么就攤上這事招拙∵篑” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵别凤,是天一觀的道長饰序。 經(jīng)常有香客問我,道長规哪,這世上最難降的妖魔是什么求豫? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮诉稍,結(jié)果婚禮上蝠嘉,老公的妹妹穿的比我還像新娘。我一直安慰自己杯巨,他們只是感情好蚤告,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著服爷,像睡著了一般杜恰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仍源,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天心褐,我揣著相機(jī)與錄音,去河邊找鬼笼踩。 笑死逗爹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的戳表。 我是一名探鬼主播桶至,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼昼伴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镣屹?” 一聲冷哼從身側(cè)響起圃郊,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎女蜈,沒想到半個月后持舆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡伪窖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年逸寓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片覆山。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡竹伸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出簇宽,到底是詐尸還是另有隱情勋篓,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布魏割,位于F島的核電站譬嚣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钞它。R本人自食惡果不足惜拜银,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望遭垛。 院中可真熱鬧尼桶,春花似錦、人聲如沸耻卡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卵酪。三九已至幌蚊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溃卡,已是汗流浹背溢豆。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瘸羡,地道東北人漩仙。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親队他。 傳聞我的和親對象是個殘疾皇子卷仑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 我們在設(shè)計接口的時候,最怕一個接口被用戶截取用于重放攻擊麸折。重放攻擊是什么呢锡凝?就是把你的請求原封不動地再發(fā)送一次,兩...
    devLionel閱讀 1,429評論 0 2
  • 說說API的防重放機(jī)制 我們在設(shè)計接口的時候垢啼,最怕一個接口被用戶截取用于重放攻擊窜锯。重放攻擊是什么呢?就是把你的請求...
    MxlZlh閱讀 2,312評論 2 18
  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,938評論 2 89
  • 1.spring對mybatis的事務(wù)管理是怎么支持的 一芭析、事務(wù)的基本原理 Spring事務(wù)的本質(zhì)其實就是數(shù)據(jù)庫對...
    __游離__閱讀 1,152評論 6 7
  • 作者:奧黛莉.潘恩 譯者:劉清彥 繪者:茹絲.哈波 出版社:上誼 推薦人:猴子老師 猴子老師導(dǎo)讀: 「面對改變的不...