From a Locked-Down Citrix Desktop to a Domain Shell
Real red team finding, fully masked. The organization, its domain, hostnames, and internal addresses have been replaced with placeholders. Nothing here points at a real environment.
Published web bugs get all the attention, but some of the most satisfying work happens inside a corporate build that was designed to hold you in place. This one was a Citrix environment at a financial institution, the kind of setup where staff and third parties log into a published desktop and are meant to touch only the handful of apps IT allows. No command prompt. No file system. No way to reach the network underneath. A sealed glass box.
The whole value of a locked down Citrix or VDI environment is containment. If a contractor's laptop is compromised, the blast radius is supposed to stop at the glass. My job on this engagement was to find out whether the glass actually held. It did not.
The address bar remembers what the GUI forgot
I started with the most boring app available, the file manager. In the published desktop the C drive was hidden. You could not see it, could not browse to it, the graphical view simply pretended it was not there. Hiding something from the GUI is not the same as denying access to it though, and file managers have a feature that quietly ignores the GUI entirely: the address bar.
I typed a path directly:
C:\
The drive opened. Hidden from the menus, fully reachable the moment you ask for it by name. That single step is the difference between "the user cannot see the file system" and "the user cannot access the file system," and only the second one is a control.
Now I could wander. I browsed to a folder that should never have been readable by a session user:
C:\TempCitrix\RDP-W7\
Inside were saved Remote Desktop connection files, left over from provisioning, sitting with permissions that let any session user open them. Two of them pointed at internal session hosts. Ready made shortcuts into the network the glass box was supposed to hide.
A leftover file becomes a door
I opened one of the RDP files and logged in with ordinary personal domain credentials, the sort of account that should have been denied at every layer here:
DOMAIN\jdoe
Access was granted. That should not have happened. The account had no business initiating a remote desktop session to these hosts, and yet the connection went through. As it connected, the machine threw up a message that made the second problem obvious:
Another user is signed in. If you continue, they will be disconnected.
Two things fall out of that one dialog. First, I could force another user off their active session, which is an availability hit and a sign that sessions were being shared or overlapped rather than isolated per user. Second, the fact that logging in bumped someone else means the isolation model was not really per user at all. User separation, the thing containment depends on, was not being enforced.
I now had a desktop session on an internal host, reached from inside a supposedly sealed environment, using a normal domain account.
The command prompt they blocked was one dialog away
Citrix had clearly been told to block shells. Launching cmd or powershell as an application was denied, exactly as policy intended. Application level blocking sounds like a control, but it only covers the paths the blocker knows about. The Run dialog is a different path.
From inside the RDP session I pressed the oldest trick on Windows:
Win + R → cmd → Enter
A command prompt opened. The Citrix application restriction never applied here, because I was no longer asking Citrix to launch an app. I was on a domain joined desktop asking Windows to run a program. Same for PowerShell in some sessions. The block was real at one layer and completely absent at the one that mattered.
With a shell, I did light, careful enumeration. Just enough to prove where I was and what I could reach, nothing destructive:
hostname
ipconfig
net localgroup administrators
whoami /groups
That returned the host's name, an internal address on a corporate subnet, the local administrator group membership, and the local accounts on the box. From a sealed glass box I now had a domain context, a shell, a view of the internal network range, and the account layout of an internal host. That is the exact foothold real intrusions are built on: a place to stand, a shell to work from, and enough network visibility to pick the next hop.
Why this chain matters more than any single step
No individual step here is exotic. Typing C:\ into an address bar, opening an .rdp file, pressing Win plus R. Junior stuff. The severity comes from the chain, because each link defeats a control that the layer around it assumed was doing the work.
- The GUI hid the C drive, and assumed hidden meant inaccessible. The address bar disproved that.
- The RDP files sat in a world readable folder, and assumed being undocumented meant being safe. Browsing disproved that.
- The domain would grant RDP to an account that should have been denied, and assumed network placement was enough. The login disproved that.
- Citrix blocked shells as applications, and assumed that covered every way to start one. The Run dialog disproved that.
- Sessions overlapped between users, and assumed the platform enforced isolation. The disconnect prompt disproved that.
Confidentiality: an unauthorized user reaches internal hosts and enumerates network ranges, hostnames, and accounts. Integrity: with a shell and a foothold, modification and privilege escalation become the next objective. Availability: forcing legitimate users off their sessions is disruption on demand. And lateral movement: a shell plus RDP access is the launch pad for everything that comes after. The glass box leaked in five different places, and the leaks compounded.
Closing every gap in the chain
Because the finding is a chain, the fix is a set of independent locks, and you want all of them, because any single one breaks this specific path while the others harden the environment against the next one.
Lock down the leftover files. Delete C:\TempCitrix\RDP-W7\ or apply NTFS permissions so only administrators can read or launch those RDP files. Provisioning artifacts should never survive into a user reachable path.
Enforce RDP access by explicit group, not by network reach. Configure the "Allow log on through Remote Desktop Services" right to name a specific management group only, remove Authenticated Users and broad domain groups, and put an RD Gateway or firewall rule in front so only management subnets and hardened jump boxes can even reach the hosts.
Fix session isolation. In the Citrix and RDP configuration, enforce per user session assignment and disable shared sessions that let a different login take over or bump an existing user.
Block shells at the layer that counts. Application blocking inside Citrix is not enough when the session lands on a full Windows desktop. Use AppLocker or WDAC to deny cmd.exe and powershell.exe for non admin groups with an allow list of the apps people actually need. GUI level or launcher level blocking is a speed bump, not a wall.
Assume the file manager address bar exists. Any control that depends on hiding a path in the GUI is already bypassed. Restrict access with permissions and policy, never with visibility.
The takeaway
Containment is only as strong as its weakest assumption, and locked down builds are full of assumptions: hidden equals inaccessible, undocumented equals safe, blocked as an app equals blocked everywhere. A red team's job is to find the one place each assumption is wrong and line those places up into a path. Here the path ran from an address bar to a domain shell, entirely out of parts that were each supposed to be someone else's problem.
The glass looked solid from the inside. It usually does, right up until you press on the corner nobody tested.