#aforismi #racconti #libri #hacking #diario

Malware.js (fatto in casa)

11.04.2023
Era un pomeriggio inoltrato, di un mesetto primaverile. Io sedevo in una clinica psichiatrica [what?!] davanti ad un ThinkPad Lenovo anteguerra [arciwhat?!] a scrivere codice. Sì, scrivevo un piccolo script Ajax per caricare dinamicamente i contenuti di questo stesso blog su cui io scrivo. E ciò che a questo è seguito, ebbe dello stupefacente. Stavo scrivendo il tutto in JavaScript: un linguaggio lato client. Per quelli che non lo sanno diciamo pure in maniera imprecisa e non esaustiva, che JavaScript è interpretato dalla macchina che lo visualizza (il tuo computer) e non da quella dove risiede (il server). Il server lo invia così com'è alla macchina, lei lo interpreta e lo trasforma in qualcosa di tangibile o meno per l'utente (i.e. il sito web). JavaScript (similmente all'HTML o ai CSS) è un linguaggio interpretato dal browser (i.e. Firefox, Chrome) e non dal server del sito che cerchiamo (i.e. google.com). [P.s. ci sono anche versioni lato server di JavaScript, come Node.js, ma per ora soprassediamo]. Ora, però, io non stavo scrivendo soltanto in JavaScript, ma in Ajax; un acronimo che sta per: Asynchronous JavaScript and XML. È una tecnologia recente, che permette lo scambio di dati in background fra server e client, a pagina già carica. Mentre prima di Ajax, una volta carica la pagina non poteva più contattare il server, con questa tecnologia può succedere, e soprattutto succede in background. Ma dunque cosa significa? Bene, vediamo le funzioni, che non brillano certo per eleganza, a cui stavo lavorando: function getPost(){ $.ajax({url: "file.php", method:"GET", data:{data: pID}, success: function(results){ if(results.length > 10){ $('#posts').append(results); }else{ getPost(); } } }); pID++; } Questa funzione apparentemente funzionava bene… (e dov'è che ho letto che quando qualcosa funziona, non bisogna più toccarla, poi…?) Comunque, essa chiedeva al file "file.php" il contenuto di un post. Passandogli un numero {data: pID} poteva segnalare quale post voleva dalla lista numerata di essi presente sul lato server sotto forma di Array. Se otteneva un risultato "results" lo aggiungeva ai post già presenti con .append, altrimenti chiamava getPost() un'altra volta fino a che non trovava un post effettivo. Così facendo con {data: 0} otteneva il primo. Con {data: 1} il secondo. E nel caso in cui il secondo non avesse (results.length > 10), ossia restituisse un post vuoto, viene chiamato getPost() con {data: 3}. Ma chi chiamava getPost()? Chi la avvia? $(window).scroll(function(){... $(document).ready(function(){... Sono le due funzioni utilizzate qui: ogni volta che la pagina è scrollata e/o ad ogni refresh della pagina stessa getPost() è lanciato. Tutto ciò funzionava, certo; eppure c'era un problema insito nelle funzioni asincrone che dava qualche incertezza. Esse si eseguono fuori dal flow della pagina. Ovverosia?! Beh, il programma quando le incontra le lancia, ma non aspetta il loro completamento per passare all'istruzione successiva. Così facendo, però, io nel $(document).ready... non potevo mettere: getPost(); getPost(); getPost(); Perché così facendo ottenevo solo che la funzione che finiva prima delle tre, rilasciasse il risultato. Questo avveniva perché tutte e tre le funzioni venivano eseguite in background, senza aspettarne il completamento si passava, diciamo ad "altro". Quindi la seconda che finiva mostrava il risultato (con .append(results)) e lo attaccava sotto la prima. In questo modo il post che si carica prima si mostra sempre in anticipo, e non il primo, ossia quello con {data: pID} minore. Cominciai a fare delle prove sia modificando lo script, sia il file in PHP che risiedeva sul Server. Un pomeriggio di lavoro per annientare questa funzione, con vari metodi (conosciuti e non) fruttarono un'idea malsana. Con l'aggiunta di piccolo loop while [ahia!] (un loop che si esegue finché certe condizioni sono rispettate), le chiamate asincrone si moltiplicavano esponenzialmente [arciahia!]. Non solo la pagina non si caricava. Ma più andava peggio era. Avrei potuto correggerlo o tornare indietro alla versione precedente, no? Certo, tutto quanto su un computer non "anteguerra" sarebbe risultato solo nella chiusura della pagina (o magari con un kill del processo di Firefox). Ma il computer era un ThinkPad Lenovo T-410, montava Linux Mint [Slackware… Debian… perdono!], e inoltre eseguiva Firefox, che per suo buon cuore, conserva le schede aperte per la prossima apertura. Così dopo aver piantato il computer, e avermi costretto ad un hard reboot (pressione del bottone fisico) me lo ritrovo piantato nuovamente appena apro Firefox. Con la mia scheda in bella mostra lì, che elabora questo loop insolubile e il computer impallato che si surriscalda. Riesco a chiuderla dopo attese infinite e nervosismo parossistico. Modifico con vim gli errori fatti, e riavvio Firefox per l'ennesima (fallimentare?) volta. No, il sito funziona. Oddio, funziona… Non direi… Ma almeno adesso non è un malware…
#hacking

iononquadro

Sono un appasionato di scrittura e di programmazione/hacking. E sono anche un malato psichiatrico. Questo blog è un luogo di sfogo di quello che sono, e costruzione di quello che sarò. Dai un'occhiata in giro, ti piacerà!

Commenti:

Attenzione: i commenti sono sottoposti a moderazione, prima di essere pubblicati.