怎么添加網(wǎng)站百度網(wǎng)盤(pán)下載電腦版官方下載
承接前面幾篇文章的觀點(diǎn),本文用一個(gè)安全攻擊的例子說(shuō)明為了解決一個(gè)傷害很低的低概率問(wèn)題,會(huì)引入多么大的麻煩,這次是可怕的被攻擊 (⊙o⊙)。
TCP 端口號(hào)只有 16bit,序列號(hào)只有 32bit,這意味著在強(qiáng)大攻擊算力面前,它很容易會(huì)被 Blind In-Window Attacks 傷害。比如,如果一個(gè)針對(duì)知名服務(wù)器 80 端口的攻擊者恰好猜對(duì)了 sport,并且使用 in_window 的序列號(hào)偽造了 SYN 報(bào)文(or RST,Data…)發(fā)給服務(wù)端,服務(wù)器將重置正常的連接,這種攻擊隨著主機(jī)內(nèi)存的增加從而 window 的增加而更加容易。
為了讓這種 Blind In-Window Attacks 更難以實(shí)施,RFC5961 引入了 Challenge ACK 的概念,如果收到莫名其妙的異常報(bào)文(比如異常 SYN,RST),將重置的責(zé)任推給發(fā)送方:
- 向發(fā)送方發(fā)一個(gè) Challenge ACK,如果果真是發(fā)送方發(fā)生了異常,收到 Challenge ACK 后自然會(huì)自行 RST 連接,否則就是遭受了 Blind In-Window Attack。
多么好的創(chuàng)意,卻弄巧成拙。
設(shè)計(jì)者意識(shí)到 Blind In-Window Attacks 可能會(huì)帶來(lái)海量的 Challenge ACK 報(bào)文注入網(wǎng)絡(luò)占用帶寬資源,從而導(dǎo)致另一類(lèi) DDoS Attack,于是提出 ACK Throttling 方案:在固定時(shí)間段(比如 1 分鐘)只發(fā)送固定數(shù)量(比如 100)個(gè) Challenge ACK。
是不是很完美?是也不是,說(shuō) “是” 因?yàn)橄氲降膯?wèn)題都解決了,說(shuō) “不是” 因?yàn)榭傆邢氩坏降?。下面是一個(gè)閉環(huán):
- 為解決 Blind In-Win Attacks => 引入 Challenge ACK => 造成潛在 DDoS => 引入 ACK Throttling => 為 Blind In-Win Attack 提供了有效信息 => Blind In-Win Attack 實(shí)施更容易,不再 Blind!
下面是一個(gè)攻擊圖示:
如 Linux 常規(guī)配置的 Throttling thresh 是 1 分鐘 100 次,攻擊者只需要與熟知端口服務(wù)器創(chuàng)建正常連接,然后發(fā)送一個(gè)猜測(cè)的 sport,seq 攜帶 SYN 的報(bào)文,緊接著在 1 分鐘內(nèi)在合法連接 conn-2 中發(fā)送 100 個(gè) In-Win 的 RST,如果攻擊者收到了 100 個(gè) Challenge ACK,說(shuō)明猜錯(cuò)了,繼續(xù)改變 sport,seq,如果它收到了 99 個(gè) Challenge ACK,說(shuō)明猜對(duì)了,因?yàn)橛幸粋€(gè) Challenge ACK 發(fā)給了被攻擊者 A,是不是很有趣?
緊接著,知道了 sport,攻擊者便可以用同樣的方法猜測(cè) seq 和 ack 來(lái)注入數(shù)據(jù)了。是不是機(jī)關(guān)算計(jì)太聰明,反誤了卿卿性命?
針對(duì)這(又一個(gè),yet another)個(gè)問(wèn)題,我曾經(jīng)本想著提交一個(gè)派池,不再用固定的 threshold,而是用隨機(jī)數(shù),一會(huì)兒換一個(gè),當(dāng)我查代碼時(shí),發(fā)現(xiàn)在 4.7 版本已經(jīng)更正了:
/* RFC 5961 7 [ACK Throttling] */
static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
{.../* Then check host-wide RFC 5961 rate limit. */now = jiffies / HZ;if (now != challenge_timestamp) {u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;challenge_timestamp = now;WRITE_ONCE(challenge_count, half +prandom_u32_max(sysctl_tcp_challenge_ack_limit));}count = READ_ONCE(challenge_count);if (count > 0) {WRITE_ONCE(challenge_count, count - 1);NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);tcp_send_ack(sk);}
}
而在此之前,它長(zhǎng)這樣:
/* RFC 5961 7 [ACK Throttling] */
static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
{.../* Then check the check host-wide RFC 5961 rate limit. */now = jiffies / HZ;if (now != challenge_timestamp) {challenge_timestamp = now;challenge_count = 0;}if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);tcp_send_ack(sk);}
}
但天知道會(huì)不會(huì)有引入另一個(gè)問(wèn)題,一定會(huì)。
講這個(gè)故事的技術(shù)細(xì)節(jié)不是本意,我想表達(dá)的是,不要為解決一件小事而引入復(fù)雜的機(jī)制?;氐?RFC5961 之前,SYN,RST 的 Blind In-Win Attack 發(fā)生多嗎?成功概率大嗎?不是因?yàn)樗锌赡馨l(fā)生就一定要去解決它。此外,針對(duì)安全問(wèn)題,我一向的觀點(diǎn)是 “不與陌生人說(shuō)話(huà)”,你說(shuō)的每句話(huà)都在透露信息,如果非要說(shuō),那么 “說(shuō)謊,并且每次說(shuō)不同的謊”,真相不重要,重要的是指紋,不要讓人猜到你的特征。
浙江溫州皮鞋濕,下雨進(jìn)水不會(huì)胖。