崩溃!还未修复的 Bug,凌晨三点遭到黑客 DDoS 攻击 | 技术头条
【CSDN编者按】互联网时代的鏖战,未必看得见烟火,但却同样让人抓狂。本文的作者,以记叙文的方式,亲自诉说了自己是如何在午夜凌晨,花了几个小时攻克掉黑客的DDoS攻击。而这件事中所展露出来的作者的极客精神,值得我们学习。
作者 | Sergio Mattei
译者 | 弯月
责编 | 胡巍巍
出品 | CSDN(ID:CSDNnews)
漆黑的夜色,笼罩着朦朦胧胧的雾气。上了一天的课,又熬夜写代码,此刻漫长的一天终于结束了,我躺在温暖舒适的床上,很快就进入了梦乡。
突然,一阵铃声将我吵醒。我爬到床的另一边,一把抓起了放在写字台上的手机。
原来是有人打电话给我,是Makerlog的人打来的电话。
当我看到来电人的名字时,就知道出事了,而且肯定不是什么好事。
于是,我与分布式拒绝服务攻击展开了长达两个小时的鏖战。
我睡眼惺忪地开始了工作
除了那通电话外,还有很多人通过各种社交媒体尝试联系我,初步看来情况不简单。我想我知道发生了什么事情:一个简单的SPAM攻击(通过发送大量垃圾请求进行的攻击),导致服务器崩溃。
得出这个初步的结论一点也不难。Makerlog的API是非常开放的,人们很容易(有意或无意地)向服务器发送SPAM请求。
我可以立即制止这些攻击(而且也很容易)。无非就是进入管理面板,停用一些Token,并禁掉IP。前一天就发生过一次这样的攻击,不是什么大问题。
我蜷缩在被窝里,一边在心里盘算:进入管理面板,挥动几下正义之锤,然后就回去睡觉。
没想到,意外发生了。
噩耗
没想到,我根本打不开管理面板。甚至连/health都打不开。这就很奇怪了,因为Gunicorn + Uvicorn是一个超级稳定的组合,连以前的SPAM攻击都未能攻克这个网站。
由于我无法访问后台的API面板,所以我一边打电话,一边头脑逐渐清醒过来。
我问社区在这个网站发生故障之前,是否有过任何SPAM的任务。但是,令我惊讶的是,他们说没有。没有人发送垃圾邮件。
这次的情况就不妙了。
我掀开被子,打开了灯(我可怜的小鱼也被我吵醒了)。
尝试重启:
我还没有意识到问题的严重性,我想着也许是服务器挂掉了,也许是内存泄漏。
这时,我已经完全清醒了。我坐在床边,在手机上打开了JuiceSSH,想弄清楚状况。
Makerlog运行在Dokku之上,所以我的第一反应是重启受影响的应用容器。Dokku对Docker的抽象可以非常巧妙地管理基础设施,因此重启很容易(请忽略下图中的错误,当时我睡着了!)
过了一会儿,容器重启完成。我终于能够访问管理面板了,这次的攻击也可以得到解决了。
等等……
重启没管用,问题仍在继续。我重启了整个服务器,还是没用。
我打开了错误日志,尝试查找容器内是否有任何问题。但日志只是在不断地显示async/await协程的错误,所以我认为这就是问题所在。
我尝试重启了几次容器,看看能否干掉我想象中的进程死锁,但无济于事。
我终于意识到问题的严重性了。
反复观察错误后,我发现了希望:
我跳下床,打开笔记本电脑,打开了SSH,试图找出问题所在。
我盯着服务器日志来回查看,却毫无头绪。
在反复观察了这些错误后,我认为这是服务器的错误。Makerlog运行在使用了ASGI的Uvicorn之上,因此很容易出现与async / await相关的错误。这个错误涉及协同程序,所以我开始朝着这个方向展开了调查。
首先,我查看了网站上的异步代码,想看看能否找到错误。我剖析了WebSockets和数据库的查询代码,但依然一无所获。
然后,突然之间……我想起我完全忽略了一种可能性。
是不是有人在做DDoS攻击?
这也不是什么新鲜事。以前我就处理过一些SPAM攻击某个API。虽然Makerlog大约有2.3万名成员,但仍然算是相对较小且低调的服务。我不会招惹太多麻烦。
这就是一次DDoS攻击:
我错了。在看了Nginx日志后,情况就很明朗了。有人正在攻击我们的站点并在反复访问 / products/ 这个API。
这个漏洞很简单:由于一些历史原因,Makerlog的/products/ API端点从未真正支持过分页。
自网站上线以来,我从未想过Makerlog会发展到现在的规模,所以我从来也没有真正考虑过分页。
因此,请求该API端点会引发一个巨大的SQL请求,在获取数据并序列化成JSON数据时导致服务器停止响应(Django REST框架的性能弱点之一)。
这种攻击很完美,他们可以通过这种方法,让CPU的使用率达到极限,并导致整个服务器崩溃(该服务器还托管了其他正在开发中的应用)。
以前我一味地添加新功能和炫酷的东西,却没有修复服务的基本功能。一切看似无恙……直到有一天它们反咬你一口。
今天,我就反受其害了。
解决方法之一:禁用
当有人得知自己的生产服务器遭到了DDoS攻击时,都会陷入恐慌。但是我没有慌,我决定用强大的禁用,轻轻挥一挥手指,就可以打败这些攻击者。
于是,我通过Reliable禁掉了违规的IP地址。
结果:不管用
等等……不管用。即使反复检查了UFW之后,我仍然能看到我禁掉的几个IP发来的请求。攻击仍在继续。噩梦并没有结束。
解决方法之二:推送补丁
经过一番思考,我认为目前最好的解决方案是阻止漏洞。通过一个包含分页的新API,我可以从根本上防止这个API消耗大量的CPU,并缓和攻击,但代价是一些使用API的应用会遭到破坏,而且网站上的产品页面将无法正常工作。
我知道这是一个非常简单的改动,所以,我很快在Makerlog的/products/ API上打上了补丁,并推送到Dokku,然后耐心地等待部署完成。结果:奏效了!
这个小小的改动之后,服务器的负载明显减少了,站点暂时恢复了。
然而,这场胜利只是短暂的。
解决方法之三:转移到CloudFlare
同时,在得到了社区的一些建议之后,我决定转移到CloudFlare上。转移的过程很快,如果我将API设置为“受攻击”模式,CloudFlare就会对可疑的地址进行严格的核实。
结果:奏效了!
CloudFlare的效果很难凭经验判断,但根据我对攻击后的分析,我可以说CloudFlare对于缓解攻击有很大的帮助,并减轻了服务器上的负载。我大力支持CloudFlare(免费的套餐就很好)!
问题得到了解决!我们安全了!对吗?
现在问题得到了解决!我们安全了!对吗?
并没有。不一会儿,我发现Nginx日志出现了奇怪的情况……攻击者们紧张起来了,他们开始抓取所有API,他们在寻找可利用的API......
很快,他们就找到了一个。Discussion的API也有同样的问题,因此改正这个API很容易(因为我现在知道原因了)。于是,我推送了一个补丁,攻击基本上就停止了。
攻击终于停止了,我长长地呼出了一口气。
整个攻击持续了大约2个小时,从凌晨3点到凌晨5点。
出现这种状况的原因
整个问题都是由于我的经验不足造成的。
Makerlog从一开始就非常开放。API一直处于欢迎所有人的状态,因为我们希望开发人员在此基础上构建新功能,但这是一把双刃剑:一方面,我们建立了一个充满激情的开发人员社区,为Makerlog构建了优秀的工具;另一方面,这种做法滋生了今晚这样的攻击。
由于开放性,Makerlog在很大程度上依赖于对用户的信任和严格的审核。我完全信任我的用户。这不是第一次有人故意利用API发起攻击,却是第一次造成严重持久的伤害。
信任因素不是唯一的原因。我迟迟没有修复分页的问题,因为我优先考虑了改善现状的方向和愿景。
我错了。
随着网站的发展,有一些不法分子也混了进来,所以现在必须采取另外一种方法了。
得到的教训
如今,我打算采用新的方法。今天,我采取了一些措施来防止将来再发生这类的攻击。
我会做的事情:
改Bug的优先度高于新功能。
实现新的限制和访问控制功能,以防止这些攻击。
采取新的API安全措施,从信任优先模型转变为预防措施。
我不会做的事情:
过度封锁API——我们的开发社区非常有价值!
轻易放过这些攻击。
让不法分子得逞!
下面,让我们来详细谈谈。
优先改Bug:
最近Makerlog发生了很多变化。我最近推出了Wellness更新,而且我们确实做了大量工作。
然而,我采取了一个让我很后悔的做法:我优先考虑了新功能,而忽略了改Bug,这导致了此次攻击的发生。我知道分页是一个问题,但是我从来没有打这个补丁,因为我觉得这不算大问题。
现在我要重申一件重要的大事:我保证今后一定及时修复明显的Bug和漏洞。我非常重视用户的信任和安全,我绝不允许发生任何可怕的事情。
Makerlog上从来没出现过任何严重的漏洞——大多数都是访问控制的问题(比如编辑其他人的任务等等)。而且这样的问题我用一只手就能数得过来。
你的数据在我这里是安全的。我重视你的信任和隐私,这一点不需要任何怀疑。
我为这个工作优先级的问题道歉,我保证以后不会再发生这样的事情。
实现访问控制的功能:
随着用户群和覆盖面的增长,不法分子与好人的比例也在增长。
如上所述,Makerlog一直采用关于API访问的信任优先模型。这种过度的用户信任会导致滥用,今后我会转向采用“预防措施优先”的方法。
Makerlog的开发社区非常优秀。新的Makerlog集成不断涌现,这是我最喜闻乐见的事情。
但是,在经历了这次事件之后,我将实施更严格的控制。我不会完全锁定API,但是会采取限制措施和其他预防措施来防止未来再发生这样的攻击。
感谢
在这里,对James Ivings和Mubaris NK等朋友表示衷心的感谢,感谢他们帮助我应对了这次攻击,并找到了根本原因。此外,还要感谢社区,感谢你们在艰难时期也能提供支持。
总结
昨晚,我在网上遭遇了不法分子。
我很荣幸地说,作为一个社区,我们已经征服了。
这是一次值得借鉴的教训。我会从这次事件中吸取教训,并转化为积极学习的动力——因为这才是我们和公司发展的途径。
原文:https://sergiomattei.com/posts/handling-the-jerks/
作者:Sergio Mattei
本文为CSDN翻译,转载请注明来源出处。
【End】
热 文 推 荐
戳他↓↓↓
☞华为或向苹果出售 5G 芯片;拼多多回应苹果停止供货;微信再推新功能! | 极客头条
☞“入职 6 年,新人工资高我 2 千”:老板不加钱,不是嫌你老
☞特斯拉Q1销量大跌,马斯克吹出的“交付100万”如何破?| 极客头条
☞2019年技术盘点微服务篇(二):青云直上云霄 | 程序员硬核评测
System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"