Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie

Door , , 35 reacties

De RyuJIT-compiler in de laatste versie van .Net blijkt een ernstige bug te bevatten, waardoor in sommige gevallen functies met de verkeerde waarden worden aangeroepen. De bug doet zich alleen voor bij het toepassen van bepaalde optimalisaties in releasemodus.

Ontwikkelaars van de website StackOverflow ontdekten de bug. In releasemodus worden bepaalde optimalisaties toegepast bij het uitvoeren van de code. De optimalisatie van tail calls leidt in .Net 4.6 tot problemen. In sommige gevallen worden daardoor de parameters van functieaanroepen gevuld met ogenschijnlijk willekeurige waarden.

Tail calling is een optimalisatie waarbij een aangeroepen functie, die de laatste is een reeks, niet op een nieuwe stack frame wordt uitgevoerd, maar de frame van zijn caller gebruikt. De parameters van functies die als tail calls worden uitgevoerd kunnen worden gevuld met ogenschijnlijk willekeurige waarden. De bug doet zich voor bij door IIS gehoste webapps, maar niet bij applicaties die in de command prompt draaien.

De bug lijkt niet direct te misbruiken maar kan indirect wel een veiligheidsrisico vormen. Zo zouden gebruikers bijvoorbeeld onbedoeld meer mogelijkheden kunnen krijgen binnen een applicatie. Daarnaast zou de verminderde stabiliteit een probleem kunnen vormen. Op GitHub is inmiddels een pull request met een oplossing geplaatst. Wanneer Microsoft een update uitbrengt, is nog niet bekend.

Moderatie-faq Wijzig weergave

Reacties (35)

Toch nog even wat correctie op dit Tweakers.net artikel (klok-klepel).

Dit bug heeft niet alleen effect op IIS, maar ook op desktopapplicaties. Het gaat hier om applicaties die het .NET framework 4.5 of hoger refereren. Niet om .NET 4.0 or .NET 2.0 applicaties. Het probleem hierbij is dat van de stack in een functie (zeg maar 'de spullen op het bureau van een functie') aan de functie bij één van de parameters een verkeerde waarde kan doorgeven.

Dit kan:
• Zorgen voor een crash. Bijvoorbeeld een getal doorgeven waar een functiepointer verwacht wordt. Of de CPU gaat daadwerklijk op die locatie aangegeven door het getal code uitvoeren, dan wordt het een beveiliginglek.
• Zorgen voor datacorruptie. Bijvoorbeeld als ik op de stack deze getallen heb: 3, 8, 9. De functie hoort met 8 en 3 aangeroepen te worden maar wordt feitelijk met 8 en 9 aangeroepen. In dit geval krijg je geen crash maar blijft alles mooi doorlopen. Vervolgens sla ik het getal op of geef ik het door aan een ander systeem die aanneemt dat de waardes kloppen.

Omtrent het actief misbruiken van de bug: je kan stellen dat dat niet gaat. Je moet precies van de draaiende applicatie weten hoe de onderliggende MSIL ('Microsoft .NET assembly' voor de leken) in elkaar zit en vervolgens ook nog hoe je specifiek bij de functie moet komen die het slachtoffer is en specifiek die de juiste inputs door te geven. Er zijn makkelijkere manieren om een systeem te hacken.

Wat wél gezegd moet worden is dat deze bug enkel tijdens de eerste compilatie van een functie naar machinecode lijkt op te treden. Niet bij de volgende uitvoeringen van een functie. Desalniettermin is het natuurlijk een ernstige bug en bewijst het de complexiteit van een optimaliserende JIT-compiler.

Waarom is deze bug nou zo vreemd? Het gebeurt enkel in programma's die met optimalisaties aan zijn gecompileerd (of beter gezegd met het DebuggableAttribute erin gecompileerd), welke niet aan de debugger hangen, waarbij de specifieke structuur van de code het toelaat om tail call optimization door te voeren.

Workarounds zijn zoals eerder genoemd .NET 4.6 niet installeren, het register aanpassen, of een environmental variabele instellen 'comPlus_useLegacyJit' met de waarde '1'.

[Reactie gewijzigd door Sebazzz op 28 juli 2015 14:39]

Nog ter aanvulling, zo kan je de bug zelf reproduceren https://github.com/dotnet...96#issuecomment-125568026

Verder is er inmiddels nog een bug in de RyuJIT gevonden https://github.com/dotnet/coreclr/issues/1299 (is ook inmiddels gefixed door MS)

[Reactie gewijzigd door GrooV op 28 juli 2015 14:14]

Dit bug heeft niet alleen effect op IIS, maar ook op desktopapplicaties.
De personen die de bug gevonden hebben geven zelf aan dat ze het niet kunnen reproduceren bij een console applicatie, maar alleen bij web ( IIS of Self-Hosted ). Het kan natuurlijk best zijn dat de bug ook wel optreedt in desktop applicaties, maar dat hebben ze nog niet gereproduceerd.
Zoals GrooV al linkt, is er inmiddels een reproductie gevonden middels een console applicatie.

En dan nog, de auteurs stellen dat ze het alleen in IIS konden reproduceren. Dat is iets anders dan zeggen dat het probleem zich ook echt daartoe beperkt. Het volgende puntje in die opsomming stelt ook terecht dat gezien het type bug, het in principe overal tot problemen kan leiden :)

Heb er even een feedbacktopic voor ingeschoten.

[Reactie gewijzigd door Cloud op 28 juli 2015 14:55]

Ah, ja die link had ik nog niet zien staan ;). Maar zoals ik al schreef is het feit dat je het nog niet gereproduceerd hebt inderdaad geen garantie dat de bug niet ook daar bestaat :)
edit: spuit elf is 1 minuut te laat

[Reactie gewijzigd door Roxors op 28 juli 2015 14:49]

Kleine aanvulling op je voor de rest prima post:
.. Het gaat hier om applicaties die het .NET framework 4.5 of hoger refereren..
De bug treedt ook op bij applicaties die een andere versie refereren indien de applicatie op een machine draait waar .NET framework 4.6 is geďnstalleerd.
De JitCompiler van het geďnstalleerde framework wordt namelijk gebruikt en niet degene van de target framework van de applicatie.
Dat is niet helemaal correct, het geldt voor alle applicaties die 4.0 of hoger refereren.

4.6 is namelijk een in-place upgrade van de 4.0/4.5 runtime.

Applicaties die 2.0,3.0 of 3.5 refererendraaien tegen de 2.0 runtime, en zullen dus ook die JIT gebruiken.
1.0 en 1.1 hebben beiden hun eigen runtime.
@Sebazzz dank voor de detail-uitleg.

Ter overvloedde, upgraden naar RyuJIT zodra dit opgelost is is WEL een heel goed idee. Ook de oude versies zijn niet zaligmakend. Ik heb een tijdje geleden met met MS team contact gehad over code die de oude JIT kan crashen icm. bepaalde memory access patterns.

High-level info hierover:

https://connect.microsoft...ilderaccess-runandcollect

Microsoft heeft inmiddels standaard de patch in RyuJIT ingebouwd. Alle oudere .NET Frameworks bevatten de bug en zijn tot op de dag van vandaag hiermee te crashen. We hebben niet verder onderzocht of het ook een beveiligingslek is.
Waanzinnig lastig op te sporen.
De ironie is dat de bug 4 dagen geleden is gefixt door sivarv @ microsoft, maar die change was teruggedraaid. :')
@sivarv

[Reactie gewijzigd door increddibelly op 28 juli 2015 13:42]

Dat zal dan wel een reden hebben. Misschien sloopte die change verderop wel weer iets?
De voorgestelde fix door de ontwikkelaars van StackOverflow is echter wel dezelfde. Misschien dat zij iets over het hoofd gezien hebben dat sivarv wel zag? :) Anders is het wel gek dat die rollback gedaan is, als dat echt de fix is zonder nadelen.

Wel fijn dat dit soort dingen door het open source zijn van .NET, nu inzichtelijk zijn.
Dat was een andere bug, waar de aanpassing niet voor de gewenste oplossing zorgde en daarom is teruggedraaid. Dat is vrij logisch.
Wel jammer dat je heel JIT optimization moet uitschakelen, je kunt niet enkel de tail calling strategy wat hier de boosdoener is uitschakelen om alsnog te kunnen upgraden met minimale impact. Het is nu net dergelijke fine tuning wat zoveel kan bijdragen aan de stabiliteit van een platform.
Je zou er nog voor kunnen kiezen om enkle applicaties in 32bit te draaien. Dan heb je er ook geen last van (maar dat is dan weer moeilijker in de hand te houden aangezien steeds meer applicaties naar 64bit gaan).
Je kunt Tail Call Optimization wel uitschakelen door dit te doen:
In the registry, create either of the following subkeys:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework

Then, specify the following:

Key name: TailCallOpt
Type: REG_SZ
Value: "0" (Double quotes are not required while entering in Registry editor)
Bronnen:
https://github.com/Micros...le-tail-call-optimization
http://blogs.msdn.com/b/d...he-net-framework-4-6.aspx).
Op zich is het wel een slordige fout, maar hij treedt in het veld niet zomaar op. Ook voor security issues zou ik niet direct heel erg bang zijn, want het lijkt mij vrij moeilijk om remote te exploiten. De stabiliteit en juiste werking is natuurlijk wel iets waar je je zorgen over kunt maken, maar dat zou je met flink testen ook wel tegen moeten komen.

Verder is het vrij eenvoudig te omzeilen in productie door de RyuJIT uit te schakelen:
If you have installed .Net 4.6, disable RyuJIT immediately (this is a temporary fix and should be removed when an update is released). You can disable RyuJIT via a registry setting (note: this requires an application pool recycle to take effect).
Under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework add a useLegacyJit DWORD with a value of 1
Or via PowerShell:
Set-ItemProperty -Path HKLM:\Software\Microsoft\.NETFramework -Name useLegacyJit -Type DWord -Value 1

[Reactie gewijzigd door Woy op 28 juli 2015 13:43]

Dit is juist wel een ernstig probleem (lokaal of niet maakt weinig uit), stel je dit nou eens voor:

amountToWithdraw
qtyOfStockToBuy
carbonCopyToAccountId
voltage
targetAltitude
rotorVelocity
oxygenPressure
dosageMilliliters
isAdmin

Als zoiets een verkeerde waarde krijgt dan kunnen de gevolgen gigantisch zijn :)
Natuurlijk is het een ernstige fout, dat ontken ik ook niet. Maar ik zou niet direct bang zijn voor de security, want het is niet iets dat door een aanvaller generiek misbruikt kan worden. Er zal dus specifiek per applicatie gekeken moeten worden of er lekken zitten, en dat is zonder de sourcecode te weten erg lastig. Zeker omdat het probleem niet zomaar overal optreedt, het is niet alsof elke Tail call het probleem veroorzaakt.

Het blijft natuurlijk wel een groot risico voor de goede werking van je applicatie, en kan dus grote gevolgen hebben. Mocht je belangrijke/gevoelige data bewerken dan is het ook zeker aan te raden om de RyuJIT gewoon uit te schakelen.

[Reactie gewijzigd door Woy op 28 juli 2015 14:01]

Tuurlijk kan het wel misbruikt worden. Dat een aanvaller hiermee niet een specifiek stukje code precies naar zijn wensen kan gebruiken wil niet zeggen dat het niet misbruikt kan worden.

Als een aanvaller tegen deze bug aanloopt kan hij bv een scriptje gaan schrijven die dezelfde operatie duizend keer herhaalt, en dan kijken wat voor spannende dingen hij allemaal tegenkomt.
Ik zeg nergens dat het niet misbruikt kan worden, ik geef aan dat het niet eenvoudig misbruikt kan worden. In de praktijk zal je als hacker ook niet zomaar weten dat je tegen de bug aangelopen bent.

En als je dan al tegen de bug aanloopt ben je nog steeds afhankelijk van het "random" gedrag van de server, want het is niet zo dat je zelf de data kan manipuleren. In veel gevallen zal het alleen tot een instabiele applicatie of ander datacorruptie leiden. Niet dat dat niet vervelend is, maar niet direct een security issue.

[Reactie gewijzigd door Woy op 28 juli 2015 15:18]

Maar ik zou niet direct bang zijn voor de security, want het is niet iets dat door een aanvaller generiek misbruikt kan worden.
^^Dat stukje ging het me even om. Dit doet het klinken alsof er geen security probleem is, maar dat is er wel, en het is potentieel gigantisch.
[...]
^^Dat stukje ging het me even om. Dit doet het klinken alsof er geen security probleem is, maar dat is er wel, en het is potentieel gigantisch.
Ik zou het Security risico niet als gigantisch inschalen, maar het is natuurlijk wel een erg kritische bug.
en dat is zonder de sourcecode te weten erg lastig
Dat is voor .NET nou net geen probleem, aangezien IL (de bytecode die .NET gebruikt) veel eenvoudiger te lezen is dan assembly. Praktisch net zo eenvoudig als source, zelfs, als je een decompiler gebruikt (tenzij je daar weer obfuscation overheen gegooid hebt).

Maar zelfs voor native code is "je moet de source code kennen" absoluut geen factor die een exploit minder ernstig maakt. Als je toepassing dusdanig belangrijk is dat iemand hem specifiek wil kraken dan gaat dat echt wel gebeuren. Je moet hierbij niet denken aan jouw thuisgebrouwen app om koffiepads te bestellen maar aan grote CMS'en, libraries, frameworks, dat soort veelgebruikte code (waarbij die ook nog eens veelal open source zijn). Controleren of RyuJIT die ergens verkeerd compileert is een eitje voor een kwaadwillende, want je hoeft alleen maar de resultaten van de huidige en de gepatchte compiler naast elkaar te houden. Daar dan weer een exploit uit distilleren is lastiger, maar zeker niet onmogelijk. De ervaring leert dat je daar niet luchtig mee om moet gaan.

Het is wel zo dat in dit geval de bug zo ernstig is en zoveel stuk maakt dat security niet de primaire overweging is. Ook zonder security heeft dit zoveel potentie om dingen onbetrouwbaar te maken dat je hier absoluut niet tegenaan wil lopen. Dan maar even de oude JIT-compiler.
[...]
Dat is voor .NET nou net geen probleem, aangezien IL (de bytecode die .NET gebruikt) veel eenvoudiger te lezen is dan assembly. Praktisch net zo eenvoudig als source, zelfs, als je een decompiler gebruikt (tenzij je daar weer obfuscation overheen gegooid hebt).
Echter kun je bij een web-applicatie natuurlijk niet bij de binaries komen, en alleen bij de gegenereerde HTML.
Maar zelfs voor native code is "je moet de source code kennen" absoluut geen factor die een exploit minder ernstig maakt. Als je toepassing dusdanig belangrijk is dat iemand hem specifiek wil kraken dan gaat dat echt wel gebeuren.
Security by obscurity is zeker niet goed te noemen, maar het maakt het wel degelijk veel lastiger om te misbruiken. Zelfs als er libraries gebruikt worden die vulnerable zijn, is het nog steeds lastig omdat je niet weet hoe die libraries gebruikt worden. Het zal veel eerder gebeuren dat je applicatie gewoon crashed, of verkeerde onzin waardes wegschrijft dan dat je toevallig opeens administrator privileges krijgt.

Verder wil ik ook zeker niet ontkennen dat het geen ernstige bug is, maar dat het erg lastig specifiek te misbruiken is. Het is anders dan bijvoorbeeld een buffer overflow attack waarmee custom code gedraaid kan worden.

Het grootste probleem zal inderdaad optreden bij bekende pakketten zoals CMS'en e.d. Maar ook daar is de vraag of er in de praktijk daadwerkelijk een fout optreedt.

[Reactie gewijzigd door Woy op 28 juli 2015 14:35]

targetAltitude
rotorVelocity
oxygenPressure
dosageMilliliters

Als zoiets een verkeerde waarde krijgt dan kunnen de gevolgen gigantisch zijn
Als zoiets de goede warde krijgt is er al iets fout gegaan. Lees de licentievoorwaarden maar eens: .Net is volgens Microsoft ongeschikt voor safety-critical of life-critical toepassingen.

Dat is geen loze waarschuwing: het gebruik van ongeschikte componenten in dergelijke toepassingen is grove nalatigheid, en kan leiden tot strafrechtelijke veroordelingen.
De fix is dus 1 regeltje code:
lcl->SetOper(GT_LCL_VAR);
Ongelukje zit in een klein hoekje ;)

Hiermee wordt volgens mij wel de waarde getoond van het open source zijn van .Net. De community gaat bug hunten en komt zelfs met een oplossing.
Het ontdekken van deze fout heeft niks te maken met het opensource zijn van de software. Het is gewoon aan de hand van een probleem in een productie omgeving gedetecteerd en gelokaliseerd.

Alleen het feit dat het opensource is draagt er aan bij dat de ontdekkers van het probleem ook meteen een oplossing voor kunnen dragen. Maar ik verwacht dat MS zelf ook wel een oplossing had kunnen bedenken als het probleem duidelijk gerapporteerd is ;)
Mja als ik de auteur (Matt Mitchell) zijn profiel bekijk werkt hij ook bij Microsoft. Dus misschien was ik eerder wat voorbarig dit success te wijten aan het opensourcen.

Uiteraard zitten er soms fouten in jitters en compilers. Da's bij LLVM en GCC enzo ook.

Maar het is wel mooi dat het publiek op github gebeurt. Als Microsoft deze stijl aanhoudt gaat mijn mening over hen enkel maar in de positieve richting evolueren.
Mooi hoe het opensourcen van coreclr nu al leidt tot het vinden van bugs door de community.
Dit is welliswaar een ernstig probleem, maar geen security flaw. Daarnaast vermoed ik dat er nog maar weinig installaties zijn met .Net 4.6 daar deze nog maar zeer recent beschikbaar is voor het grote publiek.
De bug zelf is geen security issue, maar het kan wel leiden tot ernstige security issues in webapps die ermee gebouwd zijn. En daarnaast ook ernstige corruptie van gegevens, crashes, lekken van privégegevens, etc.

Zeker als het een bug is die zich nonrandom voordoet, kan er reproduceerbaar misbruik van gemaakt worden, zonder dat de eigenaar er iets aan kan doen, behalve 4.6 wegslopen en 4.5 weer terugzetten.
In het geval van Java is de paniek ten alle tijden over de browser plugin zodat het de client (jouw computer) raakt; waarschijnlijk snappen veel mensen niet eens dat Java voornamelijk op de server draait waar je er eigenlijk weinig over hoort in de reguliere internet tam-tam.

Dit raakt de .NET server runtime waar men wat meer van de daden is dan van het panieken. Zie hier het beste voorbeeld ooit; niet alleen het belachelijk moeilijk te vinden probleem identificeren en rapporteren maar ook gelijk oplossingen en aanbevelingen documenteren en verspreiden. Respect voor de mensen achter Stackoverflow.
Niet alleen de server hoor. 4.6 is een in-place update voor de eerdere 4.x versies die dus ook gewoon in Windows 10 en lager terechtkomt.

Op dit item kan niet meer gereageerd worden.



Apple iOS 10 Google Pixel Apple iPhone 7 Sony PlayStation VR AMD Radeon RX 480 4GB Battlefield 1 Google Android Nougat Watch Dogs 2

© 1998 - 2016 de Persgroep Online Services B.V. Tweakers vormt samen met o.a. Autotrack en Carsom.nl de Persgroep Online Services B.V. Hosting door True