Gå til hovedindhold
Version2 it for professionelle
Forsiden

Hovedmenu

  • It-nyheder
  • Blogs
  • It-job
  • It-firmaer
  • Whitepapers
  • Opret bruger
  • Log ind
Du kan logge ind med din e-mail-adresse
Der er forskel på store og små bogstaver i adgangskoden.
Glemt adgangskode?
Se kommentarer (39)
Emner

Her er de 25 kodefejl du absolut skal undgå

Cross-site scripting og buffer overflow er med helt i toppen af en ny liste over de 25 mest udbredte programmeringsfejl. Dansk sikkerhedskonsulent opfordrer til at droppe 'farlige' C for at undgå buffer overflows.

Af Mikkel Meister Torsdag, 18. februar 2010 - 8:11

På en ny liste over de 25 mest 'populære' programmeringsfejl og deres tilhørende sårbarheder er det tre gamle kendinge, der huserer i toppen.

Cross-site scripting, SQL injection og buffer overflow indtager de tre øverste placeringer på listen, som er sammensat af en række store sikkerhedsorganisationer- og virksomheder, blandt andet SANS Institute, McAfee og National Security Agency.

Ifølge en dansk sikkerhedskonsulent er der ingen overraskelser hverken i toppen, eller på resten af listens 25 pladser.

Men derfor er den stadig god nok som 'huskeliste' for udviklere.

»Det er de sædvanlige fejl, der optræder på den. Men det er problemer, der i nogle af tilfældene har eksisteret i 20 år, så den slags lister kan være nødvendige for endnu engang at få fortalt programmører om problemerne,« siger it-sikkerhedskonsulent i Armada Hosting, Henrik Kramshøj, til Version2.

Listens nummer ét, Cross-site scripting eller XSS, er et angreb, hvor huller i dynamisk hjemmesidekode ? for eksempel PHP eller ASP ? bruges af hackere til at indlemme små bidder Javascript eller HTML på hjemmesiden.

Det kan for eksempel bruges til at lede den intetanende bruger ind på en hjemmeside med skadelig kode.

»Fejlen består i, at man stoler på input fra en utroværdig kilde. Det skyldes ganske enkelt mangel på inputvalidering fra serverens side, eller at inputvalideringen ikke er konsekvent nok,« siger Henrik Kramshøj.

Ifølge sikkerhedskonsulenten kan XSS være svær at bide skeer med, fordi det ikke altid er til at se, hvem der bliver ramt af den type angreb.

Undgå for alt i verden C Listens nummer tre ? det klassiske buffer overflow ? skyldes, at programmøren kopierer et antal bytes fra ét sted i hukommelsen til et andet uden at sikre, at destinationsbufferen er stor nok.

Dermed skrives der data til et sted i hukommelsen, som ikke er afsat til formålet, hvilket kan medføre, at programmet begynder at opføre sig mystisk.

Derudover kan det udnyttes i hackerangreb.

Buffer overflows er ofte knyttet sammen med programmeringssprogene C og C++, og det fik sidste år Microsoft til at anbefale udviklere at droppe brugen af C-funktionen memcpy(), der netop bruges til at kopiere en klump data fra ét sted i hukommelsen til en anden.

Funktionen er i sig selv ufarlig, hvis den bruges med omhu, men problemet er, at funktionen ikke 'tvinger' programmøren til at tænke over, om destinationsbufferen i hukommelsen er stor nok til at holde den klump data, der kopieres.

Microsoft anbefaler i stedet af bruge 'søsterfunktionen' memcpy_s(), der kræver destinationsbufferens størrelse som argument og dermed forsøger at få programmøren til at overveje mere omhyggeligt, hvordan han sætter sine fødder i hukommelsen.

Ifølge Henrik Kramshøj er det én af de ting, der kan være med til at skære antallet af buffer overflows ned.

»På samme måde har man funktionen strcpy() på Unix-platformen, som der også findes forskellige, bedre afarter af, blandt andet strlcpy(). Ved at bruge nogle funktioner, som ikke er så usikre, får man mere kontrol over tingene,« siger Henrik Kramshøj.

Han anbefaler dog helt at undgå programmeringssproget C, med mindre det er det eneste egnede sprog til opgaven.

»Hvis man kan undgå 'farlige' sprog som C, er det også at foretrække. Grunden til at kalde C farligt er, at meget få mennesker er i stand til at programmere sikkert i sproget,« siger Henrik Kramshøj.

C bruges typisk til maskinnære applikationer, hvor det er vigtigt at kunne styre hukommelsesforbruget stramt.

Hvis C er den eneste udvej, anbefaler Henrik Kramshøj udviklerne at ruste sig med både statiske og dynamiske analyseværktøjer, der kan analysere et C-program for potentielle sårbarheder både før programmet er kompileret, og mens det afvikles.

Henrik Kramshøj anbefaler samtidig at tage et kig på open source-projektet OWASP, der fokuserer på applikationssikkerhed (Se under fanebladet Eksterne links).

Se den komplette liste over de 25 programmeringsfejl herunder:

  1. Failure to Preserve Web Page Structure ('Cross-site Scripting')
  2. Improper Sanitization of Special Elements used in an SQL Command ('SQL Injection')
  3. Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
  4. Cross-Site Request Forgery (CSRF)
  5. Improper Access Control (Authorization)
  6. Reliance on Untrusted Inputs in a Security Decision
  7. Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
  8. Unrestricted Upload of File with Dangerous Type
  9. Improper Sanitization of Special Elements used in an OS Command ('OS Command Injection')
  10. Missing Encryption of Sensitive Data
  11. Use of Hard-coded Credentials
  12. Buffer Access with Incorrect Length Value
  13. Improper Control of Filename for Include/Require Statement in PHP Program ('PHP File Inclusion')
  14. Improper Validation of Array Index
  15. Improper Check for Unusual or Exceptional Conditions
  16. Information Exposure Through an Error Message
  17. Integer Overflow or Wraparound
  18. Incorrect Calculation of Buffer Size
  19. Missing Authentication for Critical Function
  20. Download of Code Without Integrity Check
  21. Incorrect Permission Assignment for Critical Resource
  22. Allocation of Resources Without Limits or Throttling
  23. URL Redirection to Untrusted Site ('Open Redirect')
  24. Use of a Broken or Risky Cryptographic Algorithm
  25. Race Condition

(Kilde: http://cwe.mitre.org)

Send Tweet
Udskriv

Kommentarer (39)

Opret en konto eller log ind for at følge indhold på Version2 - og bliv opdateret via e-mail eller rss

Følg kommentarer
Palle Simonsen 18. feb. 2010 - 09.00
 
Farlige sprog - hmm snarere farlige udviklere
»Hvis man kan undgå ’farlige’ sprog som C, er det også at foretrække. Grunden til at kalde C farligt er, at meget få mennesker er i stand til at programmere sikkert i sproget,«

Man kunne med lige så stor ret sige, at man skal undgå 'farlige udviklere'!. I min ringe erfaring har jeg set uforsigtige udviklere lave katastrofer - sikkerhedsmæssige og andre - i alle sprog inklusive sprog med sikkerhedsbælte (frameworks) såsom Java (J2EE), VB, C# (.NET) m.m. Jeg medgiver, at det er lidt sværere end i C. Men den beslutsomme udvikler kommer altid igennem alligevel - framework eller ej ;)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Peter Makholms billede
Peter Makholm 18. feb. 2010 - 09.23
 
Re: Farlige sprog - hmm snarere farlige udviklere

Selvfølgelig kommer den beslutsomme udvikler altid igennem. Men hvorfor skal vi se de samme ret basale standard-strukture blive opfundet igen og igen og igen? Hvis vi nu en gang for alle fik et veldesignet og sikkert sæt API'er for virkelig grundlæggende ting som streng-håndtering, lister og træer så ville mange af de sædvanlige farlige faldgruber blive fjernet uden at fjerne fleksibiliteten og styrken for dem der har brug for char* og generelle pointere.

Problemet er selvfølgelig at få tampet folk til at bruge disse API'er. Det er ikke lang tid siden jeg så et sikkerhedsproblem der skyldtes gets() - samme problematik der lade internettet ned i 1988.

(Og så selvfølgelig ikke sætte idioter til at kode i C)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Palle Simonsen 18. feb. 2010 - 09.31
 
Re: Farlige sprog - hmm snarere farlige udviklere

Måske er en del af løsningen, at se på teamsammensætningen - vi har alle sammen været begyndere. 'Gammeldags' dyder som peer-review af koden hjælper også tit.
Der findes flere biblioteker, der tilbyder en sikrere strenghåndtering m.m., men der er intet i C, der forhindrer, at man benytter bl.a. 'a pointer is a pointer is an int' til at lave lidt hurtig kode her og der. Så vi er tilbage ved kvalitetssans, vejledning og kontrol.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 18. feb. 2010 - 09.51
 
Mange er essentielt den samme fejl

[i]3. Buffer Copy without Checking Size of Input
12. Buffer Access with Incorrect Length Value
18. Incorrect Calculation of Buffer Size[/i]

Alle disse vedrører buffere, hvor størrelsen er fast, og hvor man ikke verificerer, om adgang til bufferen går ud over dennes størrelse.

[i]14. Improper Validation of Array Index[/i]

Er lidt i samme kategori, og

[i]17. Integer Overflow or Wraparound[/i]

er også beslægtet -- man overskrider (uden check) en grænse for en ressource.

Jeg er enig i, at brug af C er en stor del af problemet. Man kan selvfølgelig undgå problemerne med omhyggelig kodning, men, som Peter siger, hvorfor skal man spilde sine programmørers tid med den slags?

Det er trivielt at bygge den slags check ind i oversætteren, så der automatisk sættes køretidsverificering ind i den genererede kode. Det er endda forholdsvist nemt for oversætteren at finde 99% af de tilfælde, hvor checket er overflødigt og dermed lade være med at generere kode for det.

Et alternativ er kun at bruge datastrukturer, der udvides efter behov: Hvis man går ud over de nuværende grænser, udvides automatisk til en større grænse. Det giver dog mulighed for denne fejl:

[i]22. Allocation of Resources Without Limits or Throttling[/i]

Men det er et mindre problem: Det kan overbelaste en server, og dermed give anledning til DoS angreb, men det kan ikke alene være årsag til egentlige sikkerhedshuller.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Kim Jensen 18. feb. 2010 - 09.54
 
Re: Farlige sprog - hmm snarere farlige udviklere
Problemet er selvfølgelig at få tampet folk til at bruge disse API'er. Det er ikke lang tid siden jeg så et sikkerhedsproblem der skyldtes gets() - samme problematik der lade internettet ned i 1988.

Et klassisk problem er at mange foretrækker at skrive tingene selv, fremfor at betro sig til standard biblioteker - enten fordi de bare ikke vil, eller også fordi de ikke kender bibliotekerne.

Begge dele er til stor gene/skade, da de introducerer muligheder for problemer der var løst for mange år siden, både m.h.t. fejl og performance.

/Kim

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Carsten Sonne 18. feb. 2010 - 09.56
 
Re: Farlige sprog - hmm snarere farlige udviklere

Hvis man som udvikler ved hvad faldgrupperne er OG holder fokus på disse når man arbejder, så undgår man kendte design/kodefejl.

Det handler om at have det på rygraden. Hvis man er C programmør, så skal bufferoverflow problemet side på rygraden. Når man f.eks. bruge memcpy(), så er der en lille klokke der skal ringe.

Årsagen til fejlene opstår igen og igen er helt banal. Der er ikke fokus på konsekvenserne. Problemetikken eller konsekvenserne er enten ikke kendt eller også er de blevet klassificeret som ligegyldige af udvikleren.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 18. feb. 2010 - 10.04
 
SQL injection

Disse fejl skyldes uden undtagelse et idiotisk design af API'en til SQL: Man koder hele forespørgslen som tekst, så SQL syntaksen ikke bliver adskilt fra parametre såsom søgestrenge. Derfor kan man indsætte SQL syntaks i sine søgestrenge og få dem udført på serveren.

Der bør laves en skarp adskillelse af SQL syntaks (programmørspecificeret) og parametre (brugerspecificeret), så de ikke blandes. Det kan gøres på flere måder:

  1. Samme ide som i printf(): Indsæt i SQL syntaksen typeannoterede markører for pladser til brugerdata, og overfør brugerdata som separate parametre. Dermed kan brugerdata ikke fortolkes som SQL syntaks. Der er dog stadig risiko for, at en doven programmør bygger brugerdata ind i SQL syntaksen.

  2. Opbyg forespørgslen som en datastruktur, hvor syntaks er askilt fra parametre, sådan at der vil komme typefejl, hvis man forsøger at tolke parametre som syntaks. Det gør det dog lidt mere omstændeligt at programmere sine forespørgsler, men hvis sproget ellers har ordentlig understøttelse for datastrukturer, er det ikke så slemt.

  3. Brug Linq-lignende udvidet syntaks i programmeringssproget. Det kræver ændring af sproget, og er dermed uden for rækkevidde af en normal bibliotekskoder. Men ellers er det en god løsning.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Kim Jensen 18. feb. 2010 - 10.12
 
Re: SQL injection
Der bør laves en skarp adskillelse af SQL syntaks (programmørspecificeret) og parametre (brugerspecificeret), så de ikke blandes.

Problemet er blot at de steder hvor SQL injection sker er mest via typefrie programmeringssprog såsom PHP & ASP. Næsten alle programmeringssprog har mulighed for at lave såkaldte "prepared statements". Her kommer så yderligere et problem for specielt PHP, da man har en configurations mulighed for at slå magic quotes til, hvilket kan give yderligere sjove problemet.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Hans-Michael Varbæk 18. feb. 2010 - 10.27
 
Re: SQL injection

Hvis man implementerer prepared statements korrekt eller bruger mysql_real_escape_string() i PHP korrekt så opstår der ikke noget problem i forhold til SQL Injection.

Som regel er det faktisk ret simpelt ligesom med "encoding" af HTML-tegn hvor udvikleren bruger / implementerer htmlentities() helt forkert.

Det handler kort sagt om "Best Coding Practice" og det kan sagtens lade sig gøre. Hvis man ikke stoler på htmlentities tager det ikke mere end 5-10 minutter at lave en funktion selv som gør lige præcis det man gerne vil have den til at gøre, f.eks. fjerne html-tegn eller bytte dem ud med deres "entities" (eller noget tredje).

Et problem som en del udviklere overser er også hvis "register_globals" er slået til i PHP.ini hvilket gør at der kan opstå yderligere sikkerhedsproblemer ved udefinerede variabler som normalt er defineret "on-the-fly" hvilket efter min mening ikke bør bruges til andet end test eller udvikling men ikke et færdigt produkt.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Kim Jensen 18. feb. 2010 - 10.57
 
Re: SQL injection
Hvis man implementerer prepared statements korrekt eller bruger mysql_real_escape_string() i PHP korrekt så opstår der ikke noget problem i forhold til SQL Injection.

Her er det så at et af problemerne med PHP viser sig - nemlig de DB specifikke implementeringer! Ville være rart om PHP fra starten havde kigget let mere på Perl's DBI modul.

Et problem som en del udviklere overser er også hvis "register_globals" er slået til i PHP.ini hvilket gør at der kan opstå yderligere sikkerhedsproblemer ved udefinerede variabler som normalt er defineret "on-the-fly" hvilket efter min mening ikke bør bruges til andet end test eller udvikling men ikke et færdigt produkt.

register_globals bør aldrig under nogen omstændigheder være slået til, ingen undskyldninger der! Tillader man klyt i en fase, så kan du være 99% sikker på at det også vil være at finde i produktions koden, da man kan glemme at fjerne det.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Hans-Michael Varbæk 18. feb. 2010 - 11.20
 
Re: SQL injection

@Kim Jensen: Du har ret I at Database implementeringen i PHP sagtens kunne have været bedre, men den virker da.

Angående register_globals, så ved jeg godt at man aldrig bør slå den indstilling til, selvom der altså stadigvæk er hosting firmaer der gør det og udviklere som bruger den funktion til at sætte diverse variabler.

Derfor kan man kun konkludere at hvis man absolut skal bruge den funktion, så bør man sikre input der eventuelt kan komme fra register_globals er saniteret (renset) korrekt.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Leif Neland 18. feb. 2010 - 12.00
 
Re: SQL injection
Hvis man implementerer prepared statements korrekt eller bruger mysql_real_escape_string() i PHP korrekt så opstår der ikke noget problem i forhold til SQL Injection.

Det er nok et spørgsmål om målrettet at gå efter at få udryddet tutorials på nettet, der giver eksempler som

$sql="select * from tabel where id=".$_GET['id'];

Jeg forsøgte i en periode at poste prepared statements-udgaver af de usikre sql-kald der blev præsenteret i dk.edb.internet.webdesign.serverside-grupperne, men den opdragelsesmæssige effekt slog desværre ikke igennem...

Leif

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Anonym (ikke efterprøvet) 18. feb. 2010 - 12.06
 
Re: Mange er essentielt den samme fejl
Det er trivielt at bygge den slags check ind i oversætteren, så der automatisk sættes køretidsverificering ind i den genererede kode. Det er endda forholdsvist nemt for oversætteren at finde 99% af de tilfælde, hvor checket er overflødigt og dermed lade være med at generere kode for det.

Ja og der findes jo heldigvis programmeringssprog, hvor sådanne checks udføres run-time. Der findes også programmeringssprog, hvor det gøres under oversættelsestidspunktet.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Anonym (ikke efterprøvet) 18. feb. 2010 - 12.10
 
Re: SQL injection
1. Samme ide som i printf(): Indsæt i SQL syntaksen typeannoterede markører for pladser til brugerdata, og overfør brugerdata som separate parametre.

Kan man ikke forestille sig at det udnyttes til en snedig form for SQL injection?

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 18. feb. 2010 - 12.58
 
Re: SQL injection
[quote]1. Samme ide som i printf(): Indsæt i SQL syntaksen typeannoterede markører for pladser til brugerdata, og overfør brugerdata som separate parametre.

Kan man ikke forestille sig at det udnyttes til en snedig form for SQL injection?[/quote]

Ikke hvis biblioteket er skrevet fornuftigt. Så bliver den tegnfølge, der beskriver SQL-syntaksen, parset uden, at der skeles til parametrene udover, at en parameter indsættes, når der i SQL-syntaksen er et parameterfelt. Og denne parameter bliver [i]ikke[/i] parset som SQL-syntaks. Endvidere bør SQL-parseren verificere, at parameteren har den type, som er angivet i parameterfeltet. Ideelt set bør SQL-biblioteket kræve, at samtlige parametre angives separat fra SQL-syntaksen (selv om det er faste parametre, som ikke kan ændres af brugeren), da man dermed undgår, at en doven programmør bygger en tegnfølge, der indeholder både syntaks og brugerdefinerede parametre i stedet for at holde dem adskilt.

Men biblioteksfunktionerne skal selvfølgelig designes og skrives af kompetente programmører -- hvilket øjensynlig ikke har været tilfældet med de nuværende.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Kim Jensen 18. feb. 2010 - 13.24
 
Re: SQL injection
Du har ret I at Database implementeringen i PHP sagtens kunne have været bedre, men den virker da.

Ja, den fungerer - men det var da sågu den mest tåbelige konstruktion man kunne tænke sig. PHP udviklerne lavede en mapping af hver databases C interface, hvilket betød at funktionaliter og konventioner varierede afhængig af databasen.

Den første udgave af PHP var dybt fokuseret på Perl, så hvorfor de ikke snuppede en af de mest elegante dele af Perl, DBI, og tilføjede denne funktionalitet var mig en gåde.

Derfor kan man kun konkludere at hvis man absolut skal bruge den funktion, så bør man sikre input der eventuelt kan komme fra register_globals er saniteret (renset) korrekt.

Problemet med register_globals er at du mister al kontrol over variabel deklarationen. Dette betyder at ikke engang kan stole på dine egne interne variable, men er tvunget til at validare alt. register_globals er simpelthen så farlig at enhver der overhovedet overvejer at anvende den bør bankes gul og blå med en våd Søndags berlinger - indtil de har fattet dybden af deres egen dumhed.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Anonym (ikke efterprøvet) 18. feb. 2010 - 13.42
 
Re: SQL injection
Endvidere bør SQL-parseren verificere, at parameteren har den type, som er angivet i parameterfeltet

OK det var netop dette scenario, jeg havde i tankerne. Ellers kunne man vel foretage et DOS angreb, ved at angive en parameter, hvis representation ikke var en gyldig representation af en værdi af den definerede type.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Daniel Madsen 18. feb. 2010 - 15.09
 
Re: SQL injection
Hvis man implementerer prepared statements korrekt eller bruger mysql_real_escape_string() i PHP korrekt så opstår der ikke noget problem i forhold til SQL Injection.

At skulle foretage sig noget explicit for at gøre sine argumenter sikre (såsom mysql_real_escape_string) er en uheldig måde at implementere sikkerhed på.

Det kan godt være at man husker at gøre det for alle sine argumenter i de første 2000 SQL-kald man laver, men en eller anden dag har man kun sovet 2 timer og forsøger desperat at holde sig kørende på 10. kop espresso og så svipser den måske, uagtet hvor stor en kodeguru man tror man er ;-) Og så har man balladen...

Sikkerhed bør implementeres så det er implicit (om man så skal skrive sit eget API for at opnå det). Men det betyder ikke at udviklere skal pakkes ind i vat, potentielt farlige handlinger skal blot kræve at man foretager sig noget explicit for at få lov til at udføre dem, hvilket gør udvikleren opmærksom på at der kræves ekstra sikkerhedsmæssig opmærksomhed. Altså den omvendte model.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Per Sikker Hansen 18. feb. 2010 - 22.37
 
Re: SQL injection

Jeg tror alle er helt enige i at det er noget gøgl at man som udvikler sidder og skal huske på at escape alt input inden man konstruerer sin SQL-sætning.

Vi er også enige i at implementationerne af de forskellige databaseservere er inkonsistent og uhensigtsmæssigt.

Det er da også derfor at alle der vil noget seriøst med deres kode bruger et library, enten et de selv har skrevet til formålet, et de har hentet fra PEAR eller et der er dem tilbudt fra det framework de benytter til at interface med databasen. Og det er da også på grund af den fjollede database-implementation at PHP for længe siden fik PDO, der er en standardiseret måde at tale med et arbitrært antal forskellige databaseservere gennem samme abstraktionslag. PHP har kort sagt ikke nogen problemer på den front, det er udelukkende useriøse PHP-kodere der har et problem.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Daniel Madsen 19. feb. 2010 - 10.24
 
Re: SQL injection

Hej Per

Jeg ved ikke om det var mit indlæg du besvarede, men min fremhævelse af mysql_real_escape_string() var ikke ment som en kritik af PHP :-)

Det var blot et eksempel hvor udvikleren explicit skal huske at gøre en bestemt ting for at opnå sikkerhed. Buffer overflow checks er et andet godt eksempel og en af årsagerne til at jeg også er en af dem der mener at man så vidt muligt (givet at man altså har et valg) bør undgå C og istedet anvende højere niveau sprog hvor problemet er håndteret implicit af sproget.

Fordi selvom buffer overflow checks sidder nok så meget på rygraden, så går det indimellem galt - vi er ikke maskiner.

Det samme gælder håndtering af Cross-Site Request Forgery - det skal håndteres implicit af ens framework, således at enhver form submit skal stamme fra den originale side. Hvis udvikleren skal sidde og lave checks for dette explicit for hver eneste form submit, så vil vedkommende næsten uvilkårligt komme til at dumme sig før eller siden.

Min pointe er at implicitte sproglige- eller frameworkhåndteringer kan løse en god portion af de problemer på denne top 25 liste og at det er den eneste rigtige løsning. At stole på at vi mennesker altid husker at gøre bestemte ting i bestemte situationer er formentlig årsagen til at det stadig er de samme ting der bliver fremhævet i toppen af disse lister.

Jeg formoder at du er enig da du selv fremhæver framework-løsninger til PHP, men nu fik jeg da uddybet mit forrige indlæg lidt :-)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Rasmus Kaae 19. feb. 2010 - 12.32
 
Dårlige udviklere er vel farlige uanset programmeringssprog

Lige meget hvor godt og stabilt et programmeringssprog er, så er det vel aldrig bedre end den ringeste udvikler.

Ja, C og C++ kan være farligt. Har er der frihed til at lave pointergymnastik som kræver at man holder tungen lige i munden. Men, samme problem er vel aktuelt hvis man hopper over i C# eller Java hvor resource allokering vist nok er pakket pænt ind, men det er stadig et oplagt emne til problemer. Det samme gælder for synkronisering mellem tråde, race conditions, dead locks, osv.

Alt i alt, tænk dig om :)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Daniel Madsen 19. feb. 2010 - 13.02
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...

Rasmus:

Men der er meget stor forskel på hvor ringe den ringeste udvikler klarer sig i de forskellige sprog :-)

Rigtig mange af problemerne på denne liste afhjælpes eller undgåes helt ved at vælge det rigtige sprog eller framework til opgaven. Alternativet er at du skal sørge for at alle mand i afdelingen er eksperter ud i alle faldgruberne og det er ikke sønderligt realistisk i dagens erhvervsliv. Eksperter er dyre og kan være svære at anskaffe - det er jo sjældent dem der render rundt og er arbejdsløse. Det typiske scenarie er snarere at man anskaffer nogle udviklere som man tror på at man kan lære op - men det tager tid og det er jo ikke sådan at man kan have dem til at sidde og trille tommelfingrer indtil man tror på at de kan skrive fejl-fri kode.

Anvender man et sprog og nogle frameworks der tager hånd om de værste sikkerheds-problemer, så vil konsekvensen af en fejl typisk være at det de har lavet ikke virker - hvilket er en langt bedrer situation end at de ubevidst er kommet til at indføre et sikkerhedshul.

Det ville selvfølgelig være optimalt om vi alle var eksperter og "tænkte os om", men vi har alle forskellige erfaringsniveauer og jeg mener det vigtigste er at "eksperten" på holdet tænker sig om og enten vælger eller udvikler nogle løsninger der tager hånd om tingene for både ham selv og de mere "middelmådige" udviklere.

I sidste ende handler det om produktivitet. Det er min. en faktor 10 dyrere at rette en fejl der er røget hele vejen ud på drift-systemet, end at fange den i opløbet - og sikkerhedsfejl kan være katastrofalt dyre - derfor er det optimalt hvis man kan udrydde muligheden for at fejlen kan opstå i første omgang og det kan sagtens betale sig at gå forholdsvis langt for at opnå dette også selvom det koster nogle framework-udviklingstimer.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 19. feb. 2010 - 13.41
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Lige meget hvor godt og stabilt et programmeringssprog er, så er det vel aldrig bedre end den ringeste udvikler.

Når det drejer sig om sikkerhedshuller, så kan man sagtens lave sprog, der ikke tillader programmøren at lave sikkerhedshuller. Udover at sikre mod bufferoverløb og lignende, kan man rent faktisk i typesystemer eller med statisk analyse sikre, at usikker information ikke kan påvirke sikker information.

Man kan med andre ord lave sprog, hvor en stor klasse af sikkerhedshuller er umulige at kode, uanset om man så prøver ihærdigt på det. Det kan så også gøre det lidt mere omstændeligt at kode korrekte programmer, men hvis sikkerhed regnes som vigtig, er det en pris, man bør være villig til at betale.

Det er lidt et spørgsmål, om man vil betale lidt ekstra forud eller risikere at skulle betale en hel masse ekstra på et senere tidspunkt.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Erik Cederstrands billede
Erik Cederstrand 19. feb. 2010 - 14.36
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Når det drejer sig om sikkerhedshuller, så kan man sagtens lave sprog, der ikke tillader programmøren at lave sikkerhedshuller

Vis mig det programmeringssprog, der ikke tillader programmøren at publicere CPR-numre på kommunens hjemmeside.

Og lad nu være med at svare assembly :-)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 19. feb. 2010 - 14.49
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Vis mig det programmeringssprog, der ikke tillader programmøren at publicere CPR-numre på kommunens hjemmeside.

Hvis CPR-numre klassificeres som en fortrolig ressource og hjemmesiden som et offentligt sted, kan et typesystem sikre, at der ikke flyder information fra den hemmelige ressource til det offentlige sted.

Se f.eks. http://www.cs.cornell.edu/Info/People/jgm/lang-based-security/finalcr.ps

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Mark Gjøl 19. feb. 2010 - 15.05
 
Re: Mange er essentielt den samme fejl

Ofte når man laver noget i C eller C++ (Lad os sige, f.eks spil) så er man meget opmærksom på hastigheden. Jeg ville derfor som programmør blive meget negativ på et sprog der pladrer min kode til med ligegyldige (jeg laver den jo ordentligt) og værre: tidskrævende tjeks hver gang jeg foretager mig noget. Autogenererede tjeks bør foregå compiletime eller slet ikke - eller bør i hvert fald slås fra så snart man bygger til release.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Carsten Sonne 19. feb. 2010 - 15.11
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Hvis CPR-numre klassificeres som en fortrolig ressource og hjemmesiden som et offentligt sted, kan et typesystem sikre, at der ikke flyder information fra den hemmelige ressource til det offentlige sted.

Den form for desicplin ift. design er der nok ikke mange udviklere der har.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Erik Cederstrands billede
Erik Cederstrand 19. feb. 2010 - 15.17
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Hvis CPR-numre klassificeres som en fortrolig ressource og hjemmesiden som et offentligt sted, kan et typesystem sikre, at der ikke flyder information fra den hemmelige ressource til det offentlige sted.

Hvordan opdager dette typesystem, at brugeren har indtastet sit CPR-nummer der hvor han skulle indtaste sit telefonnummer? Der er jo ikke automagisk klistret en type på det 10-cifrede nummer. Hvordan kan et typesystem sikre, at der ikke er fortrolige data i noget input, som typesystemet betragter som ikke-fortroligt? Eller betragtes det som et allerede-eksisterende sikkerhedshul, som typesystemet ikke kan gøre noget ved?

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Anonym (ikke efterprøvet) 19. feb. 2010 - 15.21
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Hvis CPR-numre klassificeres som en fortrolig ressource og hjemmesiden som et offentligt sted, kan et typesystem sikre, at der ikke flyder information fra den hemmelige ressource til det offentlige sted.

Det er interessant at security properties udtrykkes vha. et typesystem!

I SPARK gøres det vha. information flow annoteringer. Information fra en kilde, kan aldrig flyde til et andet sted, med mindre dette specificeres eksplicit. Information fra en fortrolig kilde kan således aldrig flyde til et ikke-fortroligt sted og ligeledes kan ikke-troværdig information aldrig bidrage til at udlede troværdig information. Det giver faktisk nogle ret interessante "aha" oplevelser, når man programmerer.

Det kan selvfølgelig ikke sikre imod at en eller anden kopierer CPR-numrende ind på kommunens hjemmesider...

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Anonym (ikke efterprøvet) 19. feb. 2010 - 15.33
 
Re: Mange er essentielt den samme fejl
Ofte når man laver noget i C eller C++ (Lad os sige, f.eks spil) så er man meget opmærksom på hastigheden.

Nu er spil jo ligegyldige i denne sammenhæng, hvor vi taler om sikkerhed, men at et program er skrevet i C eller C++ borger ikke på nogen måde for hastigheden.

Jeg ville derfor som programmør blive meget negativ på et sprog der pladrer min kode til med ligegyldige (jeg laver den jo ordentligt) og værre: tidskrævende tjeks hver gang jeg foretager mig noget.

Hint: Du laver ikke din kode ordentligt - det kan jeg garantere for. Hvis man laver spil ja så kan det være ligegyldigt, men når andre lægger deres liv i dine hænder, så har du bare ikke den luksus.

De mennesker, der sidder i de to fly, der er på vej til at kollidere, vil nok foretrække at dit program til at detektere fraværet af radarseparation virker eller i det mindste detekterer når der opstår en intern fejl.

Autogenererede tjeks bør foregå compiletime eller slet ikke - eller bør i hvert fald slås fra så snart man bygger til release.

Alle checks bør foretages under statisk analyse (compile time), men derudover bør de også være slået til run-time. Der kunne jo være fejl i den statiske analyse.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Daniel Madsen 19. feb. 2010 - 15.37
 
Re: Mange er essentielt den samme fejl

Mark Gjøl: Der kan selvfølgelig være særlige tilfælde hvor performance-krav vejer tungest. Men performance-kode er også noget af det sværeste at skrive og vedligeholde da der ofte er et tradeoff imellem performance og nydelig struktureret kode, samt implicit kode-sikkerhed.

I mange tilfælde overvurderer vi betydningen af performance eller optimerer steder hvor det er uden betydning fordi vi har en teoretisk ide om at skrive kode der bruger så få clockcycles som overhovedet muligt.

Jeg mener at man istedet bør sætte sig et performance-krav for de algoritmer man skriver og så bør man måle om man lever op til dette krav - hvis ikke, så må man igang med at optimere. Men holder man sig fint indenfor kravet, så bør man prioritere læsbar og sikker kode.

Carsten:

Den form for desicplin ift. design er der nok ikke mange udviklere der har.

Og det er nok en af hoved-årsagerne til at listen ser ud som den gør :-)

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Lasse Reinholt 19. feb. 2010 - 15.57
 
Bounds checking i CPU

Man burde indføre bounds checking i CPU'en. Så behøvede der ikke længere at være så stort et kompromis mellem hastighed og sikkerhed.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 19. feb. 2010 - 16.03
 
Re: Dårlige udviklere er vel farlige uanset programmeringssp ...
Hvordan opdager dette typesystem, at brugeren har indtastet sit CPR-nummer der hvor han skulle indtaste sit telefonnummer? Der er jo ikke automagisk klistret en type på det 10-cifrede nummer. Hvordan kan et typesystem sikre, at der ikke er fortrolige data i noget input, som typesystemet betragter som ikke-fortroligt? Eller betragtes det som et allerede-eksisterende sikkerhedshul, som typesystemet ikke kan gøre noget ved?

Et typesystem kan selvfølgelig ikke se, om du taster dit CPR-nummer ind, hvor du skulle have skrevet dit telefonnummer. Men det kan sikre, at de oplysninger, du har tastet ind, ikke kan ses af andre brugere -- hverken samtidige eller fremtidige.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 19. feb. 2010 - 16.19
 
Re: Mange er essentielt den samme fejl
Ofte når man laver noget i C eller C++ (Lad os sige, f.eks spil) så er man meget opmærksom på hastigheden. Jeg ville derfor som programmør blive meget negativ på et sprog der pladrer min kode til med ligegyldige (jeg laver den jo ordentligt) og værre: tidskrævende tjeks hver gang jeg foretager mig noget. Autogenererede tjeks bør foregå compiletime eller slet ikke - eller bør i hvert fald slås fra så snart man bygger til release.

Jeg er enig i, at så mange check som muligt bør foretages inden kørsel af programmet. Men det er uafgørligt, om et givent stykke kode er sikkert eller ej, så det vil ikke være alle checks, du kan lave inden kørslen. Du har nu følgende valg:

  1. Oversætteren stopper med en fejlmeddelelse, hvis den ikke kan verifiere kodens sikkerhed.

  2. Oversætteren indsætter køretidscheck de steder, hvor den ikke kan verificere sikkerheden statisk.

  3. Oversætteren regner med, at du ved, hvad du gør, og lader dig køre den potentielt usikre kode uden checks.

Efter min mening er mulighed 1 og 2 begge udmærkede. Mulighed 1 opdager problemerne tidligt, men det kan være lidt omstændeligt at udforme sin kode, så oversætteren kan se, at den er sikker. Mulighed 2 giver maksimal fleksibilitet, men du opdager ikke problemerne så tidligt, og du kan få et performance hit.

Jeg synes til gengæld ikke, at mulighed 3 er acceptabel til formål, hvor sikkerhed har bare den mindste betydning. Sikkerhed er ikke så vigtig i spil, der ikke bruger netadgang, men så snart et program har netadgang, så kan sikkerhed ikke ignoreres.

Men hvorfor har du så meget imod potentielt tidskrævende køretidschecks? Hvis ikke du altid bruger de bedst mulige algoritmer og datastrukturer, så skyldes dine hastighedsproblemer næppe køretidscheck af tabelopslag, pointerdereferencer og lignende. Selv simple analyser eller typesystemer kan statisk verificere 99% af alle tabelopslag og pointerdereferencer, så prisen er ikke så høj, som mange tror.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Torben Mogensens billede
Torben Mogensen 19. feb. 2010 - 16.26
 
Re: Bounds checking i CPU

Det er ikke nogen dårlig ide, men det kræver, at hver lagerreference udstyres med øvre og nedre grænser. Det kalder man "fat pointers", fordi de fylder mere. Det er derfor stadig en fordel, hvis man statisk kan verificere, at der ikke er behov for bounds check.

Se http://cyclone.thelanguage.org/ for et eksempel på et sprog, der har både statisk verificerede almindelige pointers og køretidsverificerede "fat pointers". Dette sprog (Cyclone) vil have fordel af hardware support for fat pointers, men det er næppe den mest presserende flaskehals.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Jacob Christian Munch-Andersen 19. feb. 2010 - 17.04
 
Re: Bounds checking i CPU

Det er ikke gratis at fylde mere skidt i CPUen, et bounds check koster ressourcer som kunne være anvendt til at gøre CPUen hurtigere. I dette tilfælde tror jeg personligt at en CPU uden bounds check vil klare sig bedre end en med, givet en compiler som udfører en rimelig statisk analyse.

Der findes i øvrigt i moderne X86 CPUer en simplere feature som forhindrer de fleste owerflow angreb. http://en.wikipedia.org/wiki/Nx_bit

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Rasmus Kaae 19. feb. 2010 - 18.20
 
Tjaeh ...

Lige meget hvordan man vender og drejer det så kommer sikkerheden i et system an på to meget vigtige faktorer:

1) Design
2) Programmørens færdigheder

Hvis du har et sikkert design og en dygtig udvikler, så vil du i et vilkårligt sprog kunne skrive en sikker applikation.

Har du et dårligt design og en dygtig udvikler eller et godt design og en dårlig udvikler, så kan der til hver en tid komme problemer med sikkerheden (det være sig datasikkerhed eller applikationens stabilitet).

Det er korrekt at C#, Java, m.fl. er væsentlig bedre udrustet en programmeringssprog på lavere niveauer. Det er der ingen der anfægter. Hvis du bruger et ugyldigt index i et array kan det have fatale følger i et lavniveau programmeringssprog mens det i andre sprog medfører exceptions der potentielt stopper programmet (hvilket så også kan være kritisk).

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Mark Gjøl 20. feb. 2010 - 02.47
 
Re: Mange er essentielt den samme fejl
Men hvorfor har du så meget imod potentielt tidskrævende køretidschecks? Hvis ikke du altid bruger de bedst mulige algoritmer og datastrukturer, så skyldes dine hastighedsproblemer næppe køretidscheck af tabelopslag

Hvis du bare kendte til de emner der tages op i forbindelse med spilprogrammering (Hvorfor jeg netop bringer det eksempel på banen)... Hvis du har et loop der køres OFTE er vi nede i om det bedst kan betale sig at tjekke et dirtyflag eller bare lave beregningen hver gang (Hint: If-sætninger er møg langsomme!). Der optimeres på om data ligger spredt ud over rammen, eller om den ligger tæt lagret, da dette også kan betyde en del. Algoritmer og datastrukturer kan gøre en del, men hvis du pladrer dit kode til med if-sætninger og objekter (for slet ikke at tale om at oprette disse op heapen frem for på stakken) der kan undgås, så vil du alligevel sidde tilbage med et stykke software der kun kører for halvt blus - men det vil skalere godt - det er trods alt det du får ud af at vælge den rigtige algoritme.

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer
Jesper Juhl 21. feb. 2010 - 00.26
 
Lad nu være med at putte C++ i bås med C

Jeg ser teksten "Buffer overflows er ofte knyttet sammen med programmeringssprogene C og C++" og det gør mig som C++ udvikler lidt trist.
Ja, C++ har C "i maven" og det kan være ret brugbart i nogle tilfælde, men langt det meste af tiden har C++ bedre muligheder end C til at løse et givent problem og så opstår problemer som buffer overflows og lignende bare ikke.
I C kan det være ret omstændigt at sørge for at al hukommelse man har allokeret bliver frigivet (altså undgå memory leaks), men det er det altså ikke i C++ hvis bare man tænker sig en lille smule om - det er trivielt at lave små template klasser ala autoptr og lign der tager ejerskab af pointere og frigiver dem når objektet går ud af scope. Og hvis folk bare kunne vænne sig til at bruge std::vector og lign i stedet for et array på stacken eller en klump bytes allokeret via malloc() (eller new[]), så er det altså heller ikke svært at holde styr på hvor man kopiere data til (STL containers skal nok sørge for at udvide sig hvis der ikke er plads nok).
Der er langt nemmere at skrive sikker kode i C++ end C og det falder mig en anelse for brystet at de to sprog kastes i samme kasse.. De er vidt forskellige (og C++ er C ret overlegen hvis man ved hvad man foretager sig)!

  • Stem op 0
  • Stem ned 0
  • Log ind eller opret en konto for at skrive kommentarer

Tilføj kommentar

Opret en konto eller log ind for at følge indhold på Version2 - og bliv opdateret via e-mail eller rss

Følg kommentarer
Log ind herunder eller opret en bruger for at skrive kommentarer
Du kan logge ind med din e-mail-adresse
Der er forskel på store og små bogstaver i adgangskoden.
Glemt adgangskode?

Seneste nyt

Meego-afløseren Tizen klar til at tage kampen op med Android

Udgivet 23. maj 16.01Opdateret 23. maj 16.01

Massiv logning af danskernes internetbrug - men politiet bruger kun IP-adressen

Udgivet 23. maj 15.22Opdateret 23. maj 15.22

198 IBM-medarbejdere fritstillet med øjeblikkelig virkning

Udgivet 23. maj 14.28Opdateret 23. maj 15.10

Mystisk Project X afsløret: Rent flashlager giver fænomenal IOPS-ydelse

Udgivet 23. maj 14.19Opdateret 23. maj 14.19

Region sparer licens-millioner på at lukke ”Grønt System”

Udgivet 23. maj 13.22Opdateret 23. maj 13.22

Flere it-nyheder »

Tilmeld dig Version2's it-nyhedsbrev og vind den nye iPad.

Whitepapers

Kick-start your master data management initiative

Affecto Denmark

Affecto Data Quality Assessment: Er din indsigt og beslutning baseret på validt data?

Affecto Denmark

Framework til datamigrering i SAP miljøer - spar op til 50% på dine Data Migration udgifter

Affecto Denmark

Få et Data Warehouse (DW) review hos Affecto

Affecto Denmark

Ressourcehåndtering

Projectplace
  • Flere whitepapers

Seneste debat

  1. GOTO - Embracing variability

    6 comments.
    Last update 2 sekunder
    Skrevet af Poul-Henning Kamp
  2. HTML5 – det nye sort?

    8 comments.
    Last update 13 minutter 16 sekunder
    Skrevet af Preben Høj Holmberg
  3. Massiv logning af danskernes internetbrug - men politiet bruger kun IP-adressen

    1 comment.
    Last update 45 minutter 40 sekunder
    Skrevet af Jesper Lund
  4. Ny malware går efter alle browsere - også på Mac og Linux

    5 comments.
    Last update 1 time 11 minutter
    Skrevet af Lars Lundin
  5. Meego-afløseren Tizen klar til at tage kampen op med Android

    2 comments.
    Last update 1 time 16 minutter
    Skrevet af Jens Schumacher
  6. Sådan formaterer du tekst i debatten på Version2

    30 comments.
    Last update 1 time 32 minutter
    Skrevet af Jesper Lund Stocholm
  7. Minister giver e-læring i køreskolerne det røde kort

    2 comments.
    Last update 1 time 55 minutter
    Skrevet af Jens Madsen
  8. GOTO - programming with the stars

    1 comment.
    Last update 2 timer 10 minutter
    Skrevet af Johannes Ulfkjær Jensen

Mere debat »

Information

  • Kontakt redaktionen
  • Job- og annoncesalg
  • Teknisk support
  • Om Version2
  • Brugerbetingelser
  • Privatlivspolitik

Aktuelle emner

  • Agil udvikling
  • Android
  • Bruttolønsordning
  • Business Intelligence
  • Cloud computing
  • Download Windows 8
  • HTML5
  • Harddisk-priser
  • IE9
  • Intranet
  • It-sikkerhed
  • Kindle Fire
  • Multimedieskat
  • NemID
  • OS X Mountain Lion
  • Open source CMS
  • Projektledelse
  • Scrum
  • Sharepoint intranet
  • Storage
  • Ubuntu 11.10
  • Virtualisering
  • Windows 8
  • Windows Phone 7
  • iOS 5
  • iPhone 4S

Tjenester

  • Android-app
  • iPhone-app
  • RSS-feeds
Følg @version2dk
Tilmeld dig Version2's it-nyhedsbrev og vind den nye iPad.

Version2 udgives af

  • Mediehuset Ingeniøren A/S work Skelbækgade 4 1717 København V
  • Tlf. work 33265300