lunedì 12 dicembre 2011

OWASP Top 10 per parte NET gli sviluppatori 10:. Unvalidated reindirizzamenti e Attaccanti

Nella parte finale di questa serie vedremo il rischio di un redirect non convalidati o in avanti.Poiché questo è il rischio ultimo della Top 10, è anche il minimo rischio. Mentre per nulla innocuo, la metodologia OWASP Valutazione del rischio ha determinato che si svolge l'ultima in ordine.
La pratica del redirect non validati e indietro, spesso indicato come un "open redirect", appare piuttosto benigno sulla superficie. Tuttavia, può facilmente essere impiegato in combinazione con una combinazione di ingegneria sociale e altre attività dannose come ad esempio un sito web fraudolento progettato per ottenere informazioni personali o servire malware.
Che unvalidated reindirizzamento non fa altro che permette ad un aggressore di sfruttare la fiducia che un utente in un dominio particolare utilizzando come trampolino di lancio per un altro arbitrario, sito probabilmente dannoso. Anche se questo ha il potenziale per fare danni considerevoli, è anche una vulnerabilità contenzioso che alcune organizzazioni consapevolmente scelgono di lasciare aperta. Diamo un'occhiata a come funziona, come sfruttarlo quindi come proteggersi.

Definizione unvalidated redirect e in avanti

Questo è in realtà un rischio estremamente semplice da rilevare e gli exploit contro di essa può verificarsi in un certo numero di modi diversi. In qualche modo, sfruttando in realtà è molto simile a come si potrebbe affrontare un sito che è vulnerabile alle falle XSS abbiamo guardato indietro nel parte 2 di questa serie.
Ecco come OWASP riassume:
Applicazioni web spesso in avanti e reindirizzare gli utenti ad altre pagine e siti web, e utilizzare i dati attendibili per determinare le pagine di destinazione. Senza la corretta convalida, gli aggressori possono reindirizzare le vittime di phishing o siti di malware o utilizzare in avanti per accedere alle pagine non autorizzate.
Infatti la radice del problema è esattamente quello che stavamo guardando indietro nelle prime due parti della serie: dati non attendibili. Diamo un'occhiata a questa definizione daparte 1 di nuovo:
Dati non attendibili provengono da qualsiasi fonte - diretto o indiretto - in cui l'integrità non è verificabile e intenti potrebbe essere dannoso. Ciò include l'inserimento manuale utente, come i dati dei moduli, l'input dell'utente implicita come intestazioni di richiesta e l'input dell'utente costruita come le variabili stringa di query. Considerare l'applicazione di una scatola nera e tutti i dati che entrano per essere non attendibili.
OWASP definisce il rischio come segue:
Minaccia
agenti
Attacco di
Vettori
Debolezza di sicurezzaTecnico
Impatti
Affari
Impact
 SfruttabilitàMEDIA
PrevalenzaUNCOMMON
RilevabilitàFACILE
ImpattoMODERATO
 
Considerare chi può ingannare i tuoi utenti in presentazione di una richiesta al tuo sito web.Qualsiasi sito web o altra alimentazione HTML che gli utenti utilizzano potrebbe fare questo.Link attaccante non validati per reindirizzare le vittime e trucchi in clic su di esso.Le vittime sono più propensi a cliccare su di esso, dato che il link è a un sito valido.Attaccante obiettivi pericoloso in avanti per bypassare i controlli di sicurezza.Applicazioni più reindirizzare gli utenti ad altre pagine, oppure utilizzare avanti interno in un modo simile. A volte la pagina di destinazione è specificato in un parametro non convalidati, che consente agli aggressori di scegliere la pagina di destinazione.Rilevare redirect incontrollato è facile. Cercare redirect dove è possibile impostare l'URL completo.Avanti incontrollato sono più difficili, dal momento che obiettivo pagine interne.

Redirect ad esempio può tentare di installare malware o ingannare le vittime a rivelare password o altre informazioni sensibili.Pericoloso in avanti può permettere il controllo di bypass di accesso.Si consideri il valore di business di mantenere la fiducia degli utenti '. Che se ottengono di proprietà di malware? Che cosa succede se gli aggressori possono accedere a funzioni interne solo?



Quindi stiamo cercando una combinazione di dati non attendibili con l'inganno, o ciò che comunemente conosciamo come ingegneria sociale. Il risultato di tutto questo potrebbe essere il malware, furti di dati o la divulgazione di altre informazioni a seconda degli obiettivi dell'attaccante. Diamo uno sguardo a come tutto questo avviene.

Anatomia di un attacco non convalidati redirect

Facciamo un requisito abbastanza tipico: si sta costruendo un sito web che contiene collegamenti ad altri siti fuori al di fuori del vostro controllo. Nulla di strano in questo, ma si desidera tenere traccia di quali effettivamente collegamenti sono seguiti e registrare i click-through.
Ecco cosa la prima pagina del sito si presenta così:
Sito internet che riporta un link ad una pagina di reindirizzamento
Ci sono un paio di cose degne di nota sottolineare;
  1. Il dominio: supponiamo noi riconosciamo e la fiducia il fittizio mytrustedsite.com (ho aggiornato il mio file hosts per puntare a un sito Web IIS locale) e che vedendo questo nome host in un discorso ci dà fiducia la legittimità del sito e dei suoi contenuto.
  2. L'URL di destinazione del collegamento ipertestuale: potete vedere in basso nella barra di stato che lo lega al largo di una pagina chiamata Redirect.aspx con un parametro stringa di query denominata URL e un valore di http://troyhunt.com
Quello che sta succedendo qui è abbastanza auto-esplicativo, in realtà questo è il motivo per cui tutto è così facile rilevabilità. Ovviamente una volta che fai clic sul collegamento ci aspettiamo di vedere qualcosa del genere:
Browser con successo reindirizzato al sito web di destinazione
Ora immaginiamo che abbiamo visto un link a questo dominio attraverso un canale, come Twitter. Potrebbe sembrare qualcosa di simile:
Un tweet allettante l'utente a seguire un collegamento a un dominio trusted
Al meglio un osservatore casuale può dire, questo è un collegamento perfettamente legittimo. Esso stabilisce la fiducia e la credibilità del nome di dominio è riconoscibile, non c'è motivo di sfiducia e di tutti gli effetti, cliccando sul link verrà caricato contenuti legittimi sul mio sito di fiducia. Tuttavia:
Un sito non attendibile suscitando credenziali
Vedi il problema? E 'molto sottile e in effetti è lì che il cuore dell'attacco si trova: La barra degli indirizzi mostra che anche se abbiamo cliccato su un URL che chiaramente aveva il nome host del mytrustedsite.com , siamo ora in myuntrustedsite.com . Cosa c'è di più, c'è un modulo di accesso che chiede le credenziali che ci si aspetta naturalmente sarebbe stato gestito correttamente date le circostanze. Chiaramente questo non sarà il caso, in questo caso.
Bingo. Un unvalidated redirect ha appena permesso di rubare le credenziali di qualcuno.

Ciò che ha reso possibile tutto questo?

Si tratta di un attacco semplice e chiaramente è stato reso possibile da un URL artigianale come questo:
http://mytrustedsite.com/Redirect.aspx?Url=http://myuntrustedsite.com
Il codice dietro la pagina prende semplicemente il parametro URL dalla stringa di query, esegue alcune registrazione arbitrario quindi esegue un redirect che invia una risposta HTTP 302 al browser:
var url = Request.QueryString [ "Url" ];
LogRedirect (url);
Response.Redirect (url);
L'attacco è stato reso più credibile dal sito maligno avere un URL simile a quello di fiducia e il visual design essere coerente (anche se entrambe le implementazioni del campione). Non c'è niente che si può fare per l'URL simili o il branding coerente, tutto quello che resta è il controllo del comportamento nel codice sopra.

Assunzione di responsabilità

Prima di entrare bonifica, c'è un argomento che la sequenza di attacco al di sopra non è proprio la responsabilità del sito attendibile. Dopo tutto, non è il sito maligno che sta rubando le credenziali?
In primo luogo, l'attacco di cui sopra è soltanto una realizzazione di un redirect non convalidati. Una volta che è possibile controllare dove un URL legittima può atterrare un utente innocente, un intero mondo di altre opzioni aprirsi. Per esempio, che potrebbe facilmente essere stato un collegamento a un file eseguibile maligno. Un utente fa clic sul collegamento viene poi chiesto di eseguire un file. Anche in questo caso, stanno facendo clic su un noto, l'URL di fiducia così la fiducia di legittimità è alto. Tutte le UAC in tutto il mondo non cambia questo fatto.
La capacità di eseguire questo tipo di attacco tramite il vostro sito è la vostraresponsabilità, perché è il tuo marchio che poliziotti il peso di eventuali ricadute. "Ehi, ho caricato un link da mytrustedsite.com ora il mio PC è infetto." Non è una buona occhiata e si ha un interesse in questo scenario non giocare sul tuo sito.

Whitelist sono ancora importanti

Tornando a quella prima parte della serie di nuovo, ho fatto una dichiarazione molto enfatico che ha dichiarato: "Tutti gli input devono essere convalidati contro una whitelist di intervalli di valori accettabili ". Questo è ancora valido per i reindirizzamenti non validati e indietro ed è la chiave di come stiamo andando a mitigare questo rischio.
In primo luogo, il codice nel frammento precedente su eseguita alcuna convalida dei dati non attendibili (la stringa di query), sorta. Il primo porto di scalo dovrebbe essere quello di garantire che il parametro URL è infatti un URL valido:
var url = Request.QueryString [ "Url" ],
 se (! Uri IsWellFormedUriString (url,. UriKind Assoluto).)
{
  / / Con garbo uscita con un messaggio di avviso
 }
In realtà questa è la prima parte della nostra convalida whitelist perché siamo confermando che i dati non attendibili è conforme al modello previsto di un URL. Più su quello posteriore nella parte 2.
Ma naturalmente questo non fermerà l'attacco da prima, anche se attenua notevolmente il rischio di XSS. Ciò di cui abbiamo veramente bisogno è una whitelist di URL ammissibile che i dati non attendibili possono essere convalidati. Ciò esistere da qualche parte nella memoria persistente, come un file XML o un database SQL. In quest'ultimo caso, la convalida whitelist con Entity Framework sarebbe simile a questa:
var db = nuovo MyTrustedSiteEntities (),
 se (!. db.AllowableUrls.Where (u => u.Url == url) Qualsiasi ())
{
  / / Con garbo uscita con un messaggio di avviso
 }
Questo è abbastanza autoesplicativo, se l'URL non esiste nel database, la pagina non lavorati. Nella migliore delle ipotesi, tutto un aggressore può fare è manipolare la stringa di query con altri URL già nella whitelist, ma ovviamente assumendo questi URL sono affidabili, non c'è alcun vantaggio da guadagnare.
Ma c'è anche un altro approccio che possiamo prendere, che offre un maggior grado di offuscamento dell'URL per essere reindirizzati alla manipolazione ed esclude del tutto.Tornato a parte 4 ho parlato insicuro riferimenti oggetto diretto e ha mostrato il rischio creato utilizzando identificatori interni in modo pubblicamente visibile. La risposta è stata di utilizzare le mappe di riferimento indiretto che sono semplicemente un modo di esporre un identificatore pubblico di nessun significato logico che ha risolto di nuovo ad un identificatore privato internamente l'applicazione. Ad esempio, invece che inserire un numero di conto corrente in una stringa di query, una stringa temporanea e crittograficamente casuali potrebbe essere usato che poi mappata sul conto internamente bloccando così a chiunque di manipolare i numeri di conto semplicemente nella stringa di query (cioè loro incremento).
Nel caso di reindirizzamenti non convalidati, non abbiamo bisogno di avere l'URL nella stringa di query, proviamo in questo modo:
http://mytrustedsite.com/Redirect.aspx?Id=AD420440-DB7E-4F16-8A61-72C9CEA5D58D
L'intero codice sarebbe quindi simile a questa:
var id = Request.QueryString [ "Id" ];
 Guid idGuid,
 se (! Guid . TryParse (id, fuori idGuid))
{
  / / Con garbo uscita con un messaggio di avviso
 }

var db = nuovo MyTrustedSiteEntities ();
 var = allowableUrl db.AllowableUrls.SingleOrDefault (u => u.Id == idGuid),
 se (allowableUrl == nullo )
{
  / / Con garbo uscita con un messaggio di avviso
 }

LogRedirect (allowableUrl.Url);
Response.Redirect (allowableUrl.Url);
Quindi siamo ancora convalidando il tipo di dati (non più di tanto sarebbe successo con un GUID non valida in ogni caso!) E stiamo ancora controllando contro una whitelist, l'unica differenza è che c'è un po 'più di protezione contro la manipolazione e la divulgazione prima ancora di risolvere l'ID di un URL.

Implementazione referente verifica

In un caso come l'esempio in precedenza, l'unica volta che il redirect ha alcun tipo di finalità è legittima quando è utilizzato all'interno del sito, che è un'altra pagina sui link dello stesso sito ad esso. Lo scopo maligno abbiamo visto coinvolti accedere alla pagina di reindirizzamento dal di fuori del sito, in questo caso seguendo un link da Twitter.
Un meccanismo molto semplice, possiamo implementare il redirect è quello di verificare l'intestazione del referrer il browser aggiunge ad ogni richiesta. In questo caso suona un po 'estero, ecco le informazioni di intestazione il browser invia quando facciamo click che link originale sulla prima pagina del sito, quello legittimo, che è il seguente:
L'intestazione della richiesta referente per una richiesta legittima
Questo è stato catturato con Fiddler e si può vedere qui che il sito che di cui questa richiesta è stato il nostro sito attendibile. Ora diamo un'occhiata a quel referrer dal nostro attacco dannoso via Twitter:
L'intestazione della richiesta referente per una richiesta di malintenzionati
L'indirizzo referrer è URL shortener di Twitter sul dominio t.co. Il nostro sito di fiducia riceve questa intestazione e, di conseguenza, si può leggere e agire di conseguenza. Facciamo una prova:
var referer = Request.UrlReferrer;
 var = thisPage Request.Url;
 se (referente == nulla ! | | referrer.Host = thisPage.Host)
{
  / / Con garbo uscita con un messaggio di avviso
 }
Questa è una soluzione molto semplice che le regole immediatamente qualsiasi ulteriore opportunità di sfruttare il reindirizzamento non convalidato rischio. Ovviamente significa anche che non potrà mai deep link direttamente alla pagina di reindirizzamento da una risorsa esterna, ma in realtà, questo non è qualcosa che stai normalmente andando a voler fare comunque.

Offuscamento di intenti

In precedenza abbiamo guardato al seguente URL:
http://mytrustedsite.com/Redirect.aspx?Url=http://myuntrustedsite.com
Hai solo bisogno di leggere il singolo parametro di stringa di query e l'intento malizioso abbastanza rapidamente diventa chiaro. Supponendo, naturalmente, è possibile visualizzare l'URL completo e non è stato tagliato come nell'esempio Twitter precedenti, non dovrebbe essere abbastanza facile per gli utenti finali a identificare che qualcosa non è giusto?
Andiamo un po 'più creativo:
http://mytrustedsite.com/Redirect.aspx?Foo=xLv8WUcipP6WQLnNyA6MQzyFfyFNqCcoe&Bar=deyZWmQ4dbRtFTEDWczt72D&Url=%68%74%74%70%3a%2f%2f%6D%79%75%6E%74%72%75%73%74%65%64%73%69%74%65%2E%63%6F%6D&Foo2=CMVDnzwpWzp3PtMFJUvCwX6bxr8ecFyy&Bar2=UYuu2XRcQUKzt3xYfemWHM6HNKt
Questo eseguirà nella esattamente allo stesso modo come l'URL precedente, ma l'intento è stato offuscato da una combinazione di parametri ridondanti stringa di query che distogliere l'attenzione da quello maligno combinato con codifica URL di reindirizzamento valore che lo rende completamente illeggibile. Il punto è che non si può aspettare anche gli utenti più diligente per individuare un potenziale invalidato riorienta l'attacco incorporato in un URL.
Nel caso in cui questo suona molto teorico, è proprio l'attacco che è stato montato contro di eBay qualche tempo fa. In realtà questo attacco particolare rispecchiato il mio esempio da più indietro in termini di utilizzare un URL offuscato con il dominio eBay per poi reindirizzare ad un sito arbitrario con marchio eBay e chiesto le credenziali (si noti l'URL). Prendete questo indirizzo:
http://cgi4.ebay.com/ws/eBayISAPI.dll?MfcISAPICommand=RedirectToDomain&DomainUrl=http%3A%2F%2F%32%31%31%2E%31%37%32%2E%39%36%2E%37%2FUpdateCenter%2FLogin%2F%3FMfcISAPISession%3DAAJbaQqzeHAAeMWZlHhlWXS2AlBXVShqAhQRfhgTDrferHCURstpAisNRqAhQRfhgTDrferHCURstpAisNRpAisNRqAhQRfhgTDrferHCUQRfqzeHAAeMWZlHhlWXh
Che reindirizzato a questa pagina:
Un sito eBay fraudelant dopo un redirect non convalidati
E il gioco è fatto: non convalidati redirect sfruttati in natura.

Unvalidated contesa redirect

Nonostante il potenziale sfruttamento e l'impatto di questo rischio è ampiamente noto, continua a verificarsi in molti siti che dovrebbero conoscere meglio. Google è uno di questi e di una ben congegnata URL come questo resta vulnerabile:
http://www.google.com/local/add/changeLocale?currentLocation=http://troyhunt.com
Ma abbastanza interessante, Google sa su questo ed è felice di lasciarlo. In realtà essi esplicitamente escludere reindirizzamento URL dal programma di vulnerabilità la loro ricompensa . Vedono alcuni vantaggi nel apertamente permettendo non validati redirect e chiaramente non percepiscono questo come un rischio vale la pena preoccuparsi:
Di conseguenza, il pannello ricompensa sarà probabilmente ritengono report URL di reindirizzamento come non-qualifica: mentre noi preferiamo mantenere il loro numero sotto controllo, riteniamo che i benefici usabilità e la sicurezza di un piccolo numero di ben implementati e redirector URL attentamente monitorati tendono a prevalere i rischi percepiti.
L'attuale caso d'uso di Google che consente questa pratica non è chiaro: è possibile che ci sia un motivo legittimo per consentire esso. Google gestisce anche un vasto impero dei servizi consumati in tutti i tipi di mode e, mentre ci possono essere usi di nicchia per questa pratica, lo stesso può essere detto di rado maggior parte delle applicazioni web.
Eppure, la loro difesa della pratica sembra anche un po 'debole, soprattutto quando sostengono un exploit di successo dipende dal fatto che dell'utente "non sarà sufficiente essere attenti a esaminare il contenuto della barra degli indirizzi dopo la navigazione avviene". Come abbiamo già visto, URL simili o quelli offuscati con gli altri parametri stringa di query può facilmente ingannare anche gli utenti diligente.
Redirect unvalidated tendono a manifestarsi più spesso di quanto ci si aspetterebbe per un tale rischio facilmente mitigato. Ho trovato uno su hp.com proprio la settimana scorsa, ironia della sorte, mentre a seguito di un link al loro strumento di sicurezza WebInspect :
http://www.hp.com/cgi-bin/leaving_hp.cgi?cc=us&lang=en&exit_text=Go%20to%20troyhunt.com&area_text=Newsroom&area_link=http://www.hp.com/hpinfo/newsroom/index.html&exit_link=http://troyhunt.com
Non so se HP prendere la stessa posizione come Google o no, ma chiaramente questo non sembra essere loro preoccupante (anche se il rischio XSS potenziale del parametro "exit_text" probabilmente dovrebbe).

Riassunto

Completamento della Top 10 con la vulnerabilità più basso rischio che anche Google non prende sul serio è quasi un po 'deludente. Ma è chiaro che c'è ancora possibilità di utilizzare questo vettore di attacco per ingannare gli utenti a rivelare informazioni o l'esecuzione di file con il presupposto che sta eseguendo questa attività su un sito legittimo.
La posizione di Google non dovrebbe farti compiacenti. Come con tutti i precedenti 9 rischi che ho scritto su, la sicurezza continua ad essere di circa stesa in strati di difesa per l'applicazione. Spesso, uno strato da solo presenta un singolo punto di guasto che possono essere evitati in modo proattivo l'attuazione difese multiple, anche se olisticamente possano sembrare ridondante.
In definitiva, unvalidated redirect sono facili da difendere. È probabile che la vostra applicazione non sarà nemmeno presentano questo comportamento per cominciare, ma se lo fa, la convalida whitelist e referenti controllo sono entrambi meccanismi molto semplici per fermare questo rischio morto nella sua tracce.

venerdì 9 dicembre 2011

Al di là di YSlow - Squeeeezing le prestazioni della rete web

Ho avuto un sacco di conversazioni con gente di recente sulle prestazioni web app. Spesso queste conversazioni sono stati in giro l'affermazione che una rete di distribuzione di contenuti (qui avanti indicato come CDN), è qualcosa che è necessario distribuire nelle prime fasi del processo di ottimizzazione di un sito web. Personalmente, vedo una CDN come ultima risorsa, ma è quello che ti rivolgi a quando tutte le altre alternative di ottimizzazione delle prestazioni sono state esaurite e avete bisogno di guadagnarsi da quel po 'di latenza ultimi spostando il contenuto più vicino al pubblico. Non è un sostituto per l'ottimizzazione buon sito web, è un miglioramento .
Uno dei problemi principali con un CDN è semplicemente questo: le persone hanno ancora connessioni merda. Non importa se riesco a mettere il contenuto nella stessa città, come il pubblico, se sono in un luogo dove "banda larga" è un 1Mb connessione o anche se hai un super-veloce, ma il servizio di 3 bambini sono tutte allo stesso tempo scaricare torrent, hai un problema. Come ben ottimizzato il sito è ora conta molto di più di quanto vicino il contenuto è a voi.
Il punto che sto facendo è questa: contenuto ben ottimizzato è re. Se si può ottenere che il video in basso da 2Mb / s fino a 500Kb / s (suona come un sacco, ma ho di frequentevedere questo tipo di scenario), o drasticamente ridurre drasticamente il numero di richieste HTTP e la dimensione del contenuto di una pagina web, si sta andando a cogliere quei benefici in qualsiasi circostanza. E 'qui che bisogna partire; ottenere questo primo diritto perché è più veloce, più economico per aggiungere le prestazioni.
Quindi mi ha fatto pensare: quanti miglioramenti possono essere fatti su un sito già ben ottimizzato, Voglio dire, uno che segna molto bene contro parametri di valutazione delle prestazioni attuali? Quanto più velocemente si può andare senza spendere dollari su un CDN?Si scopre che ci sono grandi guadagni da fare molto velocemente - e costa solo un po 'di tempo di sviluppo.

Stabilire una base

Questo non è uno di quei "Ehi, guarda questo miseramente spettacolo, siti poco ottimizzato e quanto di meglio ho appena fatto" i messaggi. No, si tratta di fare un sito ben ottimizzato e rendendolo, così, più ottimizzato.
All'inizio di questa settimana ho lanciato ASafaWeb , un ASP.NET MVC 3 app per l'analisi dinamica di vulnerabilità di sicurezza relativi a configurazione. NET siti web. Ho un idea abbastanza precisa di quello che serve per fare un sito web veloce e dal primo giorno sono stato in grado di applicare i principi fondamentali, tanto che YSlow già dato il sito di un verde molto grande "A" senza nemmeno provarci:
YSlow relazione ASafaWeb prima optimisaiton
Questo di per sé è stato un eccellente risultato, soprattutto considerando che spesso coinvolto nel guardare poveri luoghi dello spettacolo e vengono direttamente dalla scatola con una B, C o anche classe D (quelle 19 domande separate. Js non ha aiutato) . Ma questo non lo rendono perfetto non, di gran lunga. In realtà non vi è un guadagno significativo per essere in cima a questo. Ma prima di entrare in questo, cerchiamo di stabilire una linea di base.
Ecco cosa sta succedendo in prima pagina:
Prima pagina del ASafaWeb
E secondo Fiddler , ecco come è tutto l'essere caricato:
Violinista traccia di ASafaWeb prima dell'ottimizzazione
Ci sono poche cose da notare qui:
  1. Tutto diverso da quello delle immagini sta già utilizzando la compressione HTTP (le bitmap sono già ben ottimizzati). Mentre la prima risposta che mostra un corpo di 2.237 byte, in realtà è più del doppio che nella prima (5237).
  2. Richieste 3, 4 e 5 provengono tutti dal CDN Microsoft e servire i file jQuery (anche compresso).
  3. Richieste di 7 e 14 sono Google Analytics.
Per capire cosa questo assomiglia in termini di sequenza di richieste e le dipendenze, ecco la linea temporale:
Timeline di ASafaWeb prima dell'ottimizzazione
Che cosa è un po 'interessante di questo è che il file Site.css - che è 2.900 byte - è di circa sei volte di più a caricare il file di jQuery primo che è 15 volte più grande. Questo è il potere del CDN e senza dissacrante mia affermazione proprio nel paragrafo d'apertura di questo post, una CDN può essere molto utile al momento giusto . Facciamo scarico tutte quelle strade di ottimizzazione per primo.
Ora i miei risultati non saranno gli stessi di tutti gli altri. Sono a Sydney e hosting ASafaWeb su AppHarbor che pone i contenuti negli Stati Uniti piuttosto che in Australia. Questo dà un'idea della differenza di prestazioni tra le massicce richieste ASafaWeb e quelli del CDN di Microsoft (che presumo dalle figure, ha una presenza locale).
In sintesi, significa tutto questo:
Riassunto delle richieste ASafaWeb prima dell'ottimizzazione
Il bit di cui sopra è importante la durata della sequenza, la pagina si carica completamente in 2,34 secondi. Caricarlo di nuovo e ci sarà un risultato diverso, ma la mia connessione è abbastanza stabile per dare un buon livello di coerenza. E 'questa durata che si vuole scendere.
Ancora una cosa: tutto questo è stato fatto con Chrome. Altri browser potrebbero richieste sequenza in modo leggermente diverso o sostenere un diverso numero di connessioni simultanee. Indipendentemente da ciò, le ottimizzazioni a venire potranno beneficiare tutti i browser. Un sacco.

Andando oltre le nozioni di base

Ci sono quattro cose che ho intenzione di fare che ha unito, farà una differenza significativa per quanto ASafaWeb esegue:
  1. Ridurre il numero di richieste HTTP. Ogni richiesta invia ulteriori byte nell'intestazione della richiesta, riceve ulteriori byte nell'intestazione di risposta e richiede un'altra connessione TCP che sostiene l'ira di latenza di rete. Inoltre, vieta il browser da fare un'altra richiesta se ha raggiunto il numero massimo di connessioni simultanee che può tenere aperto.
  2. Ridurre la dimensione dei contenuti. Posso fare questo riducendo al minimo i file CSS e JavaScript.
  3. Utilizzare un sistema di URI dati . In breve, posto alcuni dati binari in linea nel CSS, piuttosto che fare una richiesta separata di immagine. Questo ci aiuta con il punto 1.
  4. Utilizzare un sprite immagine . Questo pone bitmap multipli nella propria immagine e usa CSS per tritarli e posizionarli. Ancora una volta, contribuisce con il punto 1.
Ora che ho detto tutto questo, io non ho intenzione di affrontarlo in tutto questo ordine. Sto per iniziare la creazione del folletto, semplicemente perché ci aiuta con alcuni degli obiettivi di cui sopra. Ho iniziato guardando il Sprite ASP.NET & Ottimizzazione quadro immagine . In teoria, questo suona bene. In pratica, ero un po 'deludente.
Fondamentalmente, l'idea è che si tira il quadro in da NuGet, whack le immagini nella cartella appena creata "App_Sprite" poi riferimento al file appena creato CSS e singole immagini attraverso alcune sintassi Razor funky. Tutto bene in teoria.
Ma i problemi che ho avuto sono state numerose e di più, perché volevo un controllo molto preciso di ogni altra cosa. In primo luogo, il modello predefinito è quello di generare un file ad alta compatibilità con CSS che utilizza lo schema URI dati (ossia in grande con un sacco di dati binari in linea e supporto limitato per i browser più recenti ), e un file di compatibilità bassa che usa solo il tuo sprite classico ( compatibilità molto ampia). Il problema è che volevo un po 'di entrambi.
Il problema inizia con la ripetizione immagini di sfondo. Sprites lavorare sul concetto di esplicita scelta di una posizione nell'immagine poi tritare X pixel pixel di larghezza e Y alto.Non si può poi prendere questa fetta e ripeterla in una data direzione a meno che l'intero sprite è esattamente la stessa dimensione come la direzione si sta ripetendo in . Ad esempio, se avete un po 'di ripetere in orizzontale sfondo, è possibile effettuare si 1px di larghezza e li pila l'uno sopra l'altro. Tuttavia, gettare nel più ampio niente e sei fuori di fortuna piatto a meno che non si estendono alla larghezza dello sprite intero. E tu sei bloccato, se si desidera uno di loro a ripetere verticalmente.
ASafaWeb ha due immagini si ripetono orizzontalmente, uno fa l'ombra sotto la barra di navigazione e l'altro fa la linea a strisce:
Ripetono orizzontalmente immagini su ASafaWeb
Sono entrambi 1 pixel di larghezza (senza bisogno di più), e 8 pixel di altezza e 3 rispettivamente. Ha anche un 1 di 1 pixel semi-trasparenti PNG che ripete in entrambe le direzioni (a volte l'elemento è in ha un bordo che io non voglio la trasparenza applicata in modo trasparente CSS è out):
Semi sfondo trasparente su ASafaWeb
Sono tutti piccoli e sono tutti adatti per l'inclusione in uno sprite insieme, soprattutto una volta che si aggiunge altre immagini.
A proposito, ci sono 5 altre immagini che appaiono come due tag <img> classico sulla pagina o come sfondi su altri elementi via CSS. Lo sprite di cui sopra e l'ottimizzazione quadro immagine funziona bene per i tag immagine, ma non ti aiuta con le immagini di sfondo nel CSS, almeno non automaticamente.
Ma la cosa che mi ha ostacolato è questa:
Sprite che è significativamente più grande le immagini sorgenti combinate
Quello che vedete qui sono le cinque immagini che si desidera creare uno sprite da. Sono evidenziate e mostrano una dimensione totale di 26.4KB. Ora guardate il file "sprite0.png" - questo è quello creato dal framework di ottimizzazione. Problema è che è del 33% maggiorerispetto ai file originali combinati. Sì, lo so, è un minor numero di richieste HTTP ed a conti fatti, sarebbe quasi certamente più veloce, ma ancora, sembra proprio sbagliato . Certo le immagini sono state tutte ben ottimizzato per Photoshop per cominciare, ma ancora, in crescita di un terzo? E questo quadro è stato uno dei migliori risultati in termini di dimensioni dell'immagine finale, ho provato una serie di altri ei risultati sono stati anche peggio.
Ed è un po 'sbagliato, perché se poi prendete questa immagine e Smush.it , si restringe piuttosto rapidamente:
Smush.it riducendo le dimensioni del file sprite del 15%
Ok, è ancora maggiore rispetto agli originali, ma quando si parla di questo livello di ottimizzazione, mi aspettavo che tipo di essere meglio ottimizzato per cominciare. Ora non posso vedere se l'ottimizzazione è stata ottenuta estraendo qualità, ai miei occhi almeno (e lo faccio tendono ad essere piuttosto pedante), non c'è nessuna perdita visibile di qualità.
Comunque, il punto di tutto questo è che il quadro di ottimizzazione ha contribuito a creare alcuni schemi dati URI, un folletto che ho poi ulteriormente ottimizzati e, naturalmente, tutte le richieste CSS per posizionare correttamente e display che sprite. Una volta che è stato fatto, ho solo bisogno di mettere mano insieme le cose nel modo che volevo.
Un po 'di tentativi ed errori portano a questo:
  1. Utilizzare schemi di URI dati per le immagini di sfondo ripetendo. Sono piccoli, facili da cadere nel già esistenti CSS e non essenziali, se un cliente non può caricare.
  2. Generare lo sprite per i restanti piccoli immagini PNG e manualmente utilizzare gli stili generato da questo nel mio attuale CSS (cioè copia e incolla).
  3. Smush lo sprite dal passaggio precedente per farlo fino ad una dimensione ragionevole.
  4. Eventuali GIF animate (ho un paio di "carico" delle sequenze), o più grande file PNG (lo sfondo della pagina è di 280 x 814 pixel), rimangono come file standalone.
Questo è tutto bello ma un altro che possiamo fare per ridurre al minimo le richieste è quella di dare uno sguardo alle due file CSS. Un paio di mesi fa ho parlato con normalize.css per stabilire una base coerente comportamentale tutti i browser. Ho mantenuto questo file separato perché volevo aggiornare facilmente in futuro. Il problema è che questo crea un'ulteriore richiesta HTTP. Bottom line: ho combinato con il file CSS esistente con il contenuto di normalizzare la cima. Fine lo stesso risultato, una minore richiesta HTTP.
Poi c'è la minimizzazione. L'idea è che i CSS e JavaScript sono notoriamente inefficienti. Tutti coloro che non torna caldo e al sicuro e rientranze grande lavoro per noi umani ma sono spreco di spazio sulla rete, il browser non si preoccupa per loro un po '. Stessa cosa con le variabili JavaScript; tutta la logica di codice pulito al mondo in termini di denominazione non significa nulla per il browser e le viti solo con l'utilizzo della larghezza di banda.
Ci sono un sacco di minimisers diverse là fuori, ma Yahoo YUI Compressor è costantemente valutato come uno dei migliori. Lasciatemi dimostrare, ecco le prime righe di ASafaWeb suo file js:.
funzione PostInvalidViewState (percorso, target) {
     var form = document.createElement ( "forma" );
    form.setAttribute ( "metodo" , "POST" );
    form.setAttribute ( "azione" , percorso);
E qui è ancora una volta, dopo YUI Compressor ha avuto la sua strada con esso:
function PostInvalidViewState(d,c){var b=document.createElement
("form");b.setAttribute("method","POST");b.setAttribute("action",d);
Non torna né più, né il rientro di più e anche i parametri del metodo più la variabile "forma" sono stati tutti convertiti in caratteri singoli. Leggibilità incubo, ma funzionalmente identici.
Accordo simile con il CSS. Ecco l'originale:
corpo
 {
   background-color : # 1F1E1E ;
   carattere : 0,8 em Verdana, sans-serif ;
   margine : 0 ;
   padding : 0 ;
   color : # 9A9898 ;
}
E ora la versione minified:
corpo { background-color : # 1f1e1e ; carattere : 0,8 em 
Verdana, sans-serif ; margine : 0 ; padding : 0 ; color : # 9a9898 }
Anche gli spazi tra attributo e valore se ne sono andati: sono letteralmente sprecato spazio (ok, brutto gioco di parole!)
Minimizzazione è grande, ma devi tenere gli originali, se vi capitasse di voler lavorare sui file di nuovo. Ho appena creato un piccolo file batch per fare tutto il lavoro sopra (combinare i CSS poi minimizzare insieme al JS), e inserire un ". Min" dopo il nome del file.
Nel caso dei CSS, ecco la linea di fondo:
immagine
Prendendo la normalize.css, whacking l'alto la parte superiore del Site.css poi minifying tutto e salvarlo come Site.min.css ha più che dimezzato le dimensioni totali ! Non solo, ma abbiamo anche una richiesta HTTP meno. Giorni felici.

Nuova misurazione

Tutti i conti sopra a nulla se non possiamo fare guadagni misurabili. Ecco il risultato finale:
Richieste violinista dopo l'ottimizzazione
L'originale 19 domande: ora 12. Questo è un buon inizio. Ma vediamo il dettaglio:
Dettaglio violinista di miglioramenti delle prestazioni dopo l'ottimizzazione
E 'più facile quando si vede un confronto diretto dei bit di veramente importante:
 
Prima
Dopo
Cambiare
Richieste
19
12
-37%
Byte inviati
15.818
9217
-42%
Byte ricevuti
121.368
119.544
-1,5%
Durata (secondi)
2,34
1,86
-20%
Noi sappiamo perché le richieste sono diminuite ei byte inviati gocce per motivi connessi; ogni richiesta include i dati di intestazione come il browser, la tua scelta (parlato) la lingua ed i cookie il sito è impostato. Ridurre le richieste, ridurre i dati inviati.
Byte ricevuti a malapena i cambiamenti e la risposta perché questo è nella inefficienza dello sprite. Anche dopo lo smushing, ha aggiunto byte che abbiamo appena superato attraverso la minimizzazione. E 'ancora una netta riduzione in byte, ma la riduzione delle richieste è stato ancora più importante.
Ma il grande - l'unica che conta veramente - è la durata preso per tutta la baracca da caricare. 20% di persone - che non è piccolo cambiamento! E ricordate, che è 20% più veloce su un pre-ottimizzate, "A" le prestazioni del sito di qualità!
Questo è un risultato molto piacevole.

Riassunto

Tutto ciò è al di sopra altamente variabile; velocità di rete vanno su e giù, diversi browser si comportano diversamente, c'è ancora tempo di rendering di prendere in considerazione, c'è vita oltre un carico di freddo (niente cache), ecc ecc Ma quando torneremo al contesto ho impostato all'inizio - quella di non pre-ottimizzazione con un CDN - spero che il punto è ormai chiaro. Un sito molto ben ottimizzato, che già implementa la compressione HTTP, le richieste minime, saranno ottimizzate le immagini e utilizza anche un CDN per alcune richieste possonoancora rendere un guadagno del 20% da appena un paio d'ore di ottimizzazione intelligente.
Il CDN è il prossimo passo. Può anche ottenere un altro 20% - o forse solo il 15%, forse 25% - Non lo so. Ma quello che so è che vi costerà un carico perso più di un paio d'ore di tempo di sviluppo. Questo è ormai il regno di aumentare esponenzialmente il tempo e dollari per lo stesso guadagno e questo è dove si vuole essere al fine di ottimizzazione la vostra gente, non all'inizio.
Oh, e solo nel caso in cui non siete convinti del valore di questo esercizio o ti sei dimenticato come ci si sente ad avere una connessione lenta miseramente (o sei troppo giovane per aver vissuto la gioia di internet più di 56kbps), provare a impostare Fiddler per simulare la velocità del modem e navigare in giro per un po '. ASafaWeb ora completamente carica in 14 secondi - non sarà possibile ottenere che su altri siti troppi!