0x00 起因
前幾天朋友跟我說他的服務器最近老是爆炸划纽,而且經(jīng)常是一到點就集體崩潰被芳,別的服主也有類似的情況萌抵,他給服務器套上全局代理之后服務器就不崩潰了兼砖,然而給服務器開了代理客戶端也連不進來篡九。一開始我猜測是BDS(Bedrock Dedicated Server抗碰,mcpe官方服務端)會與mojang服務器有連接价脾,連不上就會觸發(fā)某個bug導致崩潰随珠。
(圖片是windows服務器的內(nèi)存占用羽莺,服主windows和linux都有開)
報錯如下实昨,基本上只能得知是內(nèi)存分配相關的問題,從報錯判斷不出什么禽翼。
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
[2020-03-15 15:09:41 INFO] Package: com.mojang.minecraft.dedicatedserver
Version: 1.14.32.1
OS: Linux
Server start: 2020-03-15 14:53:05 UTC
Dmp timestamp: 2020-03-15 15:09:41 UTC
Upload Date: 2020-03-15 15:09:41 UTC
Session ID: e24ac8b6-8e41-4d53-ba6c-949b7bbcde90
Commit hash:
Build id: development
CrashReporter Key: e29bac8d-dc1e-3938-8438-413e8e159bce
Crash
[2020-03-15 15:09:41 INFO] at gsignal (UnknownFile:?)
at abort (UnknownFile:?)
at __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate[unsigned long, void const*] (UnknownFile:?)
at std::allocator_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate[std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, unsigned long] (UnknownFile:?)
at std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate[unsigned long] (UnknownFile:?)
at std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >* std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate_and_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> >[unsigned long, std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>] (UnknownFile:?)
at std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::reserve[unsigned long] (UnknownFile:?)
at PurchaseReceiptPacket::read[ReadOnlyBinaryStream&] (UnknownFile:?)
at Packet::readNoHeader[ReadOnlyBinaryStream&, unsigned char const&] (UnknownFile:?)
at NetworkHandler::_sortAndPacketizeEvents[NetworkHandler::Connection&, std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >] (UnknownFile:?)
at NetworkHandler::runEvents[bool] (UnknownFile:?)
at Minecraft::update[] (UnknownFile:?)
at ServerInstance::_update[] (UnknownFile:?)
at clone (UnknownFile:?)
0x01 抓包分析
為了驗證這個想法屠橄,我連朋友的服務器抓了幾次服務器崩潰時的包,抓包用的是tcpdump闰挡,服務器開在docker容器里面锐墙,大概方法如下:
# 獲取容器PID
docker inspect --format "{{.State.Pid}}" <container id/name>
# 切換到容器的網(wǎng)絡命名空間
nsenter -n -t <container root id>
tcpdump -i eth0 -w dump.cap
但是服務器在線人數(shù)比較多,從抓到的包里面也沒分析出什么關鍵信息长酗。
0x02 問題排查
服務器還在一直崩潰溪北,不過時間段好像變化了,沒那么固定了夺脾,有時候也只是卡死一段時間之拨,服務器并沒有完全崩潰,此時除了懷疑MCPE服務器可能與mojang之間有連接之外咧叭,我慢慢地開始懷疑服主的群里面是不是有內(nèi)鬼蚀乔,但是群里面那么多人,也不好找誰是內(nèi)鬼菲茬,于是我們準備使用ip白名單的方式來排查問題吉挣,也就是把部分信任的人的ip加入防火墻白名單,如果此時還會崩潰的話婉弹,那基本就可以排除服務器是被人攻擊了的猜想睬魂,開了白名單之后服務器維持了很長一段時間穩(wěn)定運行,但是后來還是炸了镀赌。我當時有點像放棄了(服主跑路算了氯哮,哈哈哈哈哈)。
0x03 內(nèi)鬼自爆
高潮來了商佛,開了白名單的那天晚上喉钢,內(nèi)鬼自爆了姆打,這個人直接在群里面坦白說是他炸的服,并且揚言還要繼續(xù)出牧,不過當時他由于未知的原因沒有黑成功穴肘,被群友的嘲諷了一晚上(具體原因可能是那天我們把服務器換到了內(nèi)網(wǎng),用frp內(nèi)網(wǎng)穿透的方式開了服務器舔痕,目的是為了排除mcpe服務器的xbox驗證可能導致崩潰评抚,由于網(wǎng)絡環(huán)境改變導致他的攻擊方式失效了)。
不過第二天服務器還是崩了伯复,大概就可以確認是這個人搞崩的慨代,服主提前找出了這個人在群里面的所有小號以及他的ip,并把他踢了出去啸如,那天開了白名單后服務器還是崩潰了的原因是服主看白名單很穩(wěn)定侍匙,就放松了審核,不小心讓內(nèi)鬼就混了進去叮雳。在這之后服主開始了嚴格的ip白名單審核想暗,服務器終于穩(wěn)定了下來。
0x04 重現(xiàn)bug
如果這么簡單結(jié)束了的話我是不會寫這篇文章的帘不,在我得到了內(nèi)鬼的相關信息之后说莫,我想知道他是怎么攻擊的。于是我又翻出了那天一開始抓的包寞焙,用服主得到的ip在包里面匹配储狭,可是并沒有找到什么,應該是換了ip了捣郊,然后我從ip歸屬地開始查辽狈,發(fā)現(xiàn)了一個跟內(nèi)鬼同一個歸屬地的ip。
理所當然地呛牲,我開始分析這個包的行為刮萌,發(fā)現(xiàn)他在服務器崩潰時刻發(fā)出了很多連接服務器的請求娘扩,每次的client GUID
不一樣尊勿,我猜測服務端每發(fā)現(xiàn)一個客戶端連接時,不管它有沒有連進來都會給這個客戶端提前分配一段內(nèi)存畜侦,一次發(fā)送很多client GUID
不一樣的包會讓服務端誤以為有很多客戶端在連接躯保,于是內(nèi)存不夠分配服務器就崩潰了旋膳。
為了驗證這個想法,我把這段包提取出來途事,用tcpreplay重放验懊,修改好網(wǎng)絡包的mac地址擅羞,ip和端口,向一個測試服務器快速重放這些可能會導致崩服的包义图,然而减俏,持續(xù)發(fā)了好幾分鐘,服務器紋絲不動碱工,內(nèi)存占用率是一條讓人尷尬的直線娃承。
于是我開始找別的線索,抓的包里面與服務器有連接的也就十幾個ip怕篷,我挨個查了一下歸屬地历筝,查完后我驚呆了,十幾個ip里面有6個ip是來自阿里云的廊谓,排除其中兩個是服主自己的服務器梳猪,還有4個,難道真正的攻擊者是內(nèi)鬼租的云服務器蒸痹?我挨個看了一下那幾個阿里云服務器的行為春弥,倒也看不出什么太大貓膩,我順手把那些包截取出來叠荠,稍作修改后開始對測試服發(fā)送匿沛,此時,測試服瞬間崩了蝙叛,內(nèi)存占用俺祠,報錯信息和前幾天的一模一樣,然后我重新看了下這些包借帘,
我猜是這樣發(fā)包才能騙過服務器有很多客戶端在與服務器建立連接蜘渣,具體的原理已經(jīng)不太重要了,畢竟這個得去研究一下BDS的協(xié)議才能知道詳細信息肺然,bug已經(jīng)復現(xiàn)了蔫缸,向mojang提交bug才是正確方式。
0x05 后續(xù)
內(nèi)鬼被踢了之后服主的主頁被d了际起。拾碌。〗滞現(xiàn)在還是黑洞狀態(tài)