Allvarligt säkerhetsproblem med PDF-filer

Idag skriver IDG.se artikeln "Pdf-filer är hackarnas nya farliga vapen - så skyddar du dig" och förklarar det nya säkerhetsproblemet som uppdagats. Adobe uppmanar användare att snabbast möjligt ladda hem den nya versionen Adobe Reader 8 (engelska), där problemet är löst. Den svenska versionen verkar precis vara släppt, när jag kollade för en liten stund sen hittade jag den inte. Att man lanserar den med sådan hast, är i så fall ett tecken på, hur allvarligt Adobe anser problemet vara.

Huvudproblemet kan visas genom exempel nedan. På följande sätt kan man köra vilken javascript-kod som man vill på klienten. Och detta medan användaren befinner sig på den domän där PDF-filen befinner sig. En öppen vektor för cross-site-scripting-attacker, nätfiske, stöld av sessionsvariabler och cookies eller för att sprida XSS-maskar med andra ord.

http://www.entersomedomain.com/thepdfyoufound.pdf#blah=javascript:alert("This is an XSS-attack example");

Detta fungerade så länge jag hade version 7.0.8 installerad, efter jag lagt in version 8 så fungerade inte attacken längre.

De som först hittade den nya attack-vektorn var Stefano Di Paola och Giorgio Fedon. Vidare har GnuCitizen.org också gjort en bra beskrivning med inlägget "DANGER, DANGER, DANGER". Hac.kers.org är webbplatsen jag såg informationen på först, och skribenten RSnake uttryckte sig så här, om upptäckten.

IDG skriver i artikeln att säkerhetshålet bara har upptäckts i Adobes insticksmodul, men andra uppgifter tyder på att set inte slutar där. Hac.kers.org har forskat vidare på sårbarheten och menar nu att det inte bara är genom en webbläsare som en attack kan ske. Det hela diskuteras vidare på Sla.ckers.org forumet och några begynnande exempel visar upp hur även PDF:er kan utnyttjas, som ligger på användarnas datorer. Farliga länkar kan sedan spridas via skräppost eller chatt-program.

Detta verkar vara ett av de farligaste säkerhetshålen som hittats på länge, och eftersom många användare kommer ha kvar version 7 eller äldre ett bra tag, så kan vi förvänta oss att det kommer skapa problem långt framöver. Är du en webbmaster som har många PDF-filer på dina sajter, och dessutom använder AJAX av någon form, bör du genast sätta dig in i vilka riskerna är. Läs även "What you need to know about the UXSS in the Acrobat Plugin" av Jeremiah Grossman.

By Jesper Lind

XSS-mask härjade på Gaiaonline.com

Tekniken AJAX (Asynkron JavaScript och XML) används i allt större utsträckning på webbplatser. Baksidan är att detta öppnar upp för en ny typ av attacker kallade XSS (Cross-site scripting).

Idag släpptes en XSS-mask loss på community-sidan Gaiaonline.com och på bara 3-4 timmar infekterades 1500 användare. Läs mer om detta på ha.ckers.org där även källkoden för masken finns att studera.

Att förstå hur dessa XSS-attacker fungerar är väldigt viktigt för alla som jobbar med att utveckla applikationer med AJAX-funktionalitet.

By Jesper Lind

Intrången fortsätter - senaste målet LO:s hemsida

Lars Olsson meddelar att LO:s hemsida blev hackad under nyårshelgen, och visar upp en skärmdump av det politiska meddelande som aktivisterna lämnade. "Under 2007 kommer LO att kämpa för att samma usla lön" skriver de och att "medlemsavgifterna kommer att gå till att smutskasta småföretagare".

Förövarna passar även på att gäcka Polisen och förklarar att de även låg bakom attacken mot SSU, tidigare i höstas.

Meddelandet är signerat av Pablin77 och är samma signatur som användes när SOS Alarm hackades för någon vecka sedan.

Uppdatering: Fel av mig. Pablin77 tros inte ligga bakom attacken. Dennes signatur nämndes bara i ett meddelandet "Pablin77, YOU SUCK!". Attacken mot LO signerades med "Vuxna Förbannade Hackare - Det slutar inte här".

Lite andra bloggares tankar: "Så här känns det att vara hackad" på Kulturbloggen.com, "En nyårsgåva till LO" från Högerkonspiration, Johan Sjölander: "Kan inte dessa hackare skaffa flickvän, eller nått...", Nina Unesi: "Ett hack i festen" och sist men inte minst - deep|ed: "Hack i festen - hål i huvudet".

Som en parantes kan man också notera hur en svensk mediabyrå community/diskussionforum, såg möjligheten till uppmärksamhet genom att iscensätta att deras hemsida blivit hackad. Detta gjordes som ett aprilskämt i maskopi med ett antal bloggar, bland annat Bisonblog.

By Jesper Lind

Stoppa spam-bots på din sajt

Jag har spenderat lite tid för att söka efter ett bra sätt, att försvåra för spam-robotar att snappa upp emailadresser på de webbplatser jag jobbar med. Hittade lite olika lösningar som verkar mer eller mindre effektiva.

Lite olika varianter
Först tänkte jag räkna upp några av de sidor som jag besökte innan jag hittade det som kändes bäst för mig. Ett sätt som jag aldrig tänkt på innan är att använda CSS för att skydda adresserna.

Hittade också ett enkelt exempel på en javascript-variant, där man skriver ut adresserna enligt "user at example.org".

Ytterligare ett exempel finns på The Code Project. som använder en BitConverter i Asp.Net för att göra om adresserna, till något som ser ut så här: 64657266406578616D706C652E636F6D. Ett Javascript avkodar sedan strängen, så att de ser ut som vanligt för användaren. Eftersom de flesta spam-bots inte kör javascript så kan de inte se att det är en emailadress.

Använda en HttpModule för att stoppa spam
Den metod som jag valde att använda hittade jag på Webpronews.com. Den gör om emailadresserna till hexadecimala tecken. Och den gör det på ett väldigt smart sätt eftersom den blandar de hexadecimala tecknen med vanliga, enligt en slumpvis algoritm. I en webbläsare ser adresserna helt vanliga ut, men spamrobotarna kommer få problem. Det fina med att använda en HttpModule är ju att ma inte behöver koda om alla sidor på webbplatsen. Modulen tar hand om detta och applicerar det över hela sajten. För att vara ännu säkrare kan man även kombinera denna teknik med en javascript-variant.

Så här lägger man till en referens till modulen i web.config:

<httpModules>
<add type="EmailSpamModule" name="EmailSpamModule" />
</httpModules>

Själva koden för modulen läggs i App_Code och ser ut så här:

#region Using

using System;
using System.IO;
using System.Web;
using System.Text;
using System.Text.RegularExpressions;

#endregion

/// <summary>
/// Removes whitespace from the webpage.
/// </summary>
public class EmailSpamModule : IHttpModule
{

#region IHttpModule Members

void IHttpModule.Dispose()
{
// Nothing to dispose;
}

void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}

#endregion

void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app.Request.RawUrl.Contains(".aspx"))
{
app.Response.Filter = new SpamFilter(app.Response.Filter);
}
}

#region Stream filter

private class SpamFilter : Stream
{

public SpamFilter(Stream sink)
{
_sink = sink;
}

private Stream _sink;

#region Properites

public override bool CanRead
{
get { return true; }
}

public override bool CanSeek
{
get { return true; }
}

public override bool CanWrite
{
get { return true; }
}

public override void Flush()
{
_sink.Flush();
}

public override long Length
{
get { return 0; }
}

private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}

#endregion

#region Methods

public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}

public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}

public override void SetLength(long value)
{
_sink.SetLength(value);
}

public override void Close()
{
_sink.Close();
}

public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer);

html = EncodeEmails(html);

byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}

private static string EncodeEmails( string html)
{
foreach (Match match in _Regex.Matches(html))
{
html = html.Replace(match.Value, Encode(match.Value));
}
return html;
}

private static Regex _Regex = new Regex("(mailto:|)(\\w+[a-zA-Z0-9.-_]*)@(\\w+).(\\w+)");
private static Random _Random = new Random();

private static string Encode(string value)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < value.Length; i++)
{
if (_Random.Next(2) == 1)
sb.AppendFormat("&#{0};", Convert.ToInt32(value[i]));
else
sb.Append(value[i]);
}

return sb.ToString();
}

#endregion

}

#endregion

}

Jag hoppas att skaparen av detta kod tycker det är okej att jag publicerar den.
In english: I hope that the creator of this code approves that I republish it. If not, just contact me and I will remove it. I also found it here and here.

En prestandavarning
När jag provade på ett riktigt långt html-dokument så fick jag lite oväntade problem. Vet inte riktigt vad det beror på. På kortare sidor fungerar modulen bra.

En bete för bots
Till sist tänkte jag använda metoden för att lägga ut ett bete för spam-botsen. Följande adress har jag skapat endast för denna sidan och jag kommer inte lägga ut den någon annanstans. Får jag ett spam till den adressen så vet jag att en bot har överlistat systemet.

spammeifyoucan@codeodyssey.com

I koden bakom ser denna adress ut som följer, svårt för till och med en spam-bot att fatta.

s&#112;&#97;&#109;m&#101;if&#121;oucan@c&#111;&#100;&#101;o&#100;y&#115;&#115;ey.&#99;o&#109;

By Jesper Lind

Klass-fil som genererar lösenord

Här visar jag ett exempel på en bra klass för att generera lösenord. Lösenorden blir 10 tecken långa och skapas av endast tecknen a-z, A-Z, 0-9.

Det är inte jag som utspungligen skrev den men har använt den så länge att jag glömt bort vart den kommer från. Om någon känner igen koden, hör gärna av er så ska jag skriva en referens till skaparen.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Text;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// Summary description for PasswordGenerator
/// </summary>


public class PasswordGenerator : Page
{
private char[] characterArray;
private Int32 passwordLength = 10;
Random randNum = new Random();

public PasswordGenerator()
{
characterArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
}

private char GetRandomCharacter()
{
return this.characterArray[(int)((this.characterArray.GetUpperBound(0) + 1) * randNum.NextDouble())];
}

public string Generate()
{
StringBuilder sb = new StringBuilder();
sb.Capacity = passwordLength;
for (int count = 0; count <= passwordLength - 1; count++)
{
sb.Append(GetRandomCharacter());
}
if ((sb != null))
{
return sb.ToString();
}
return string.Empty;
}
}

By Jesper Lind