Using OneDrive Sync Client with C: drive restrictions (and a bunch of handy security tips too)

Let’s go have a quick delve into the age-old battle of user experience against security!

It is very important to secure your Citrix environment from attackers, but it’s also important to ensure you don’t interrupt your users’ productivity. The case of the OneDrive Sync Client in an estate that enforces C: drive restrictions is an interesting demonstration of this conundrum. This article runs through that, as well as discussing a number of ways you can improve the security of your solution against common tricks that both attackers and pentesters will leverage.

Introduction

I must mention fellow CTP Dave Brett at this point. I worked briefly with him on the deployment of a secure desktop where we came across many of the problems that I am going to discuss here, and we also did a presentation based on our experiences at the UK Citrix User Group last November (which we will be doing again for MyCUGC on June 4th, so feel free to tune in!) Dave wrote up a good number of the points I am going to touch on here, mostly in his article on local drive access and the one on PowerShell too. He also has a piece about lateral movement which I am going to touch on as well. Given that we are collaborating on the presentation hopefully this article should complement those rather than just rehashing some of the same points 🙂

One of the biggest issues we found was trying to balance security with usability, and that is the crux of the presentation subject that we wrote. A lot of environments these days are implementing what they call a “zero trust” approach – essentially trusting nothing, be it external or internal, and insisting on verification before connection. But even though this sounds like a ban-hammer situation, it is important to keep your eye on what this is trying to achieve. The zero trust approach will not protect you from being hacked – in fact, your entire mindset should be from a standpoint of “we will be breached, sooner or later”. What the zero trust approach aims to achieve in my mind is to slow down lateral movement throughout the network in order to give any breach more time to be detected and less time to commit actual data exfiltration or other nefarious activity. When an attacker gains a foothold in a system they then need to move laterally through the network searching for a weak point to attack in order to elevate privileges or access secured data. The more you can delay them at the point between foothold and vulnerability then the more chance you have of detecting the breach.

Once you adopt the “we will be hacked” mentality then your primary focus is detection and response. Good monitoring is key to this (if you’re looking for monitoring, then I am in the middle of doing a deep-dive on uberAgent, part 2 of which should be along very shortly). If you’re not auditing what your users are doing, then you can’t be expected to track the breach once you discover it – and this means that SIEM (security information and event management) is crucial. Your response to an intrusion is absolutely key – in fact, when you report it to the ICO (or whomever the responsible authority for data breaches is in your locality), you can be sure you will be judged by how you have responded. One additional thing to remember about response is that the audit data you are gathering needs to be retained – sometimes breaches can occur weeks or months in the past and finding that the logs have rolled over and overwritten themselves is the last thing you need when responding.

Good monitoring also gives you baselines which means you can measure the impact on usability of every security improvement you make. When you are trying to balance performance and security this is another utterly vital requirement. Security and usability are, unfortunately, often diametrically opposed, but it is very important to make sure that your security posture doesn’t ruin the solution from an end-user perspective. If you do, the users will either utterly reject it or even potentially start looking for ways to box around your security themselves. Do your baselining often, repeating every time you make a security change.

I will call this out here – security and performance should be given EQUAL weight within every project, and ideally, they should be balanced out against each other. Here’s a slide from our presentation that I think illustrates perfectly how we need to approach this

A couple more points to call out from a general perspective before we crack on to the details. Firstly, patching needs to be done properly. There’s no point having a burglar alarm if you’re going to leave all of the doors and windows open. If you’re not on top of patch management in all areas of your environment, then, seriously, you need to invest some time and resource onto it as soon as possible.

Secondly, defence in depth is vital. A Windows system has so many little quirks, features and shortcuts it is impossible to stay on top of it from one angle alone, particularly now that both Windows and Office are in rapid development models. You need to secure your desktops and applications, but you also need to do many other things – ensure that NTFS permissions on data and operating systems are solid, ensure that your users’ internet access is appropriately controlled, ensure that you are using approved security software, look at Conditional Access rules, network security groups, firewalls, etc., etc., etc. There are huge amount of steps you need to be taking to ensure that you have a good security posture, and there is a vast collection of information online that can help you with this. Use it!

Examples of lateral movement attempts

So I think it is possibly a good idea to demonstrate some of the ways that lateral movement can be achieved in a Citrix environment.

1. Local drives in File Explorer

Pretty easy method, just dive into the File Explorer app and start digging through the C: drive

2. The Run command

The Run command (either invoked by the WinX menu, the Win+R key, or simply searching for it in the Start Menu) offers an easy way to run commands, browse local or network drives and is a really common starting point for lateral movement

3. The Explorer address bar

File Explorer’s address bar is another common place to look for lateral movement – you can type paths, commands, UNC paths, shell commands, pretty similar to the Run command

4. Internet Explorer address bar

IE’s address bar functions pretty much the same as the File Explorer address bar and allows the same methods to be called

5. Browsers allowing access to local filesystem

They don’t work in the same way as Internet Explorer (which actually spawns a File Explorer window to local drives when invoked), but Chrome, Edge, Edge Chromium and Firefox (and probably all other browsers) can access the local filesystem simply by typing file:///c:/ or file:///d:/ or any drive letter into their address bar.

Firefox
Google Chrome
Edge Chromium (pretty much identical to Chrome)

6. Connecting to \\localhost\c$

If access to the c: drive or any other local drive is blocked, you can often circumvent it by browsing to \\localhost\c$ or whatever drive letter you require. This can be done from the Run command, File Explorer, Start Menu, or any one of the browsers mentioned previously

7. Connecting to loopback address

Similar to above, you can also browse to the network loopback address (127.0.0.1) via the Run command, File Explorer, Start Menu, or any browser

8. The command prompt

The Windows command prompt (cmd.exe) can be invoked in many ways – from the Run command, File Explorer, any browser that allows access to the filesystem, dialog boxes in applications, etc. Once in the command prompt you can run commands, access the filesystem, etc. Many of the commands you can invoke from here can access further areas of the OS too (ipconfig, reg.exe, etc., etc.)

9. PowerShell

PowerShell is like the command prompt, just more powerful and therefore worse. It can be invoked in similar numbers of ways and allows not just access to the filesystem but the Registry, various assemblies and libraries and is probably one of the first targets any attacker or pentester will aim for.

10. Drive mappings

Drives can be mapped in lots of different ways (through File Explorer menu items, from the command prompt, PowerShell, etc.) and may allow you to connect to areas that we have already highlighted as vulnerable

11. Shell commands

When the filesystem is restricted, running Shell commands such as Shell:Programs may allow a backdoor access into the filesystem

From there you can traverse back up the filesystem to find what you are looking for

12. Variables

Similar to above, sometimes you can use environment variables like %APPDATA% and %LOCALAPPDATA% to break free into the filesystem

13. The Start Menu search

An easy way is to use the Start Menu search to find things you want to use, particularly if searching for executables that may help the attacker gain a foothold

14. Common dialog boxes

Especially when using published apps, attackers often use common application dialog boxes such as those presented by Save, Print and Open dialogs to access the filesystem and run commands

15. Copying executables into the user profile

If the execution of system binaries is restricted by path or name, another trick is for the attacker to copy a system file (like PowerShell.exe) into their own profile and run it from there after renaming it. Here is an example of a command they might run to achieve it

cmd.exe /c copy c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe %USERPROFILE%\Desktop\ps.exe

The renamed PowerShell copied to the desktop

16. The subst command

Subst.exe is very useful for an attacker particularly because it allows them to map to a local path rather than a network one. This can circumvent drive restrictions in explorer if the attacker can run it like this

subst x: c:\

17. Create a shortcut

Attackers can create shortcuts to things like batch files or OS commands that may allow them to break out of the restrictions. A very common way is to create a shortcut to ftp.exe, which then allows the user to run like a command prompt simply by putting ‘!’ in front of the commands they wish to execute

18. Write malicious dll to install directory outside of Program Files folders

Users commonly have the ability to create folders in the root drive on modern Windows versions. However they do not have the ability to write to the Program Files or Windows folders. If you have a piece of software that installs itself outside of these two areas, an attacker could load a malicious dll or binary in the path somewhere and have it executed.

19. Registry editing tools

Registry editing tools like regedit.exe, regedt32.exe, reg.exe, PowerShell, etc. can allow an attacker into the depths of the OS.

20. Control Panel applets

Some Control Panel applets or the Settings tool can allow the user to navigate into areas of the filesystem or into settings they should not be tinkering with

21. Services configurations

Services are a common attack vector as well. Unquoted service paths and faulty permissions on services can allow attackers a foothold that can be exploited very badly.

Dave B has an article describing the problems with unquoted service paths already so let’s not belabour that area 🙂

If services have been created with faulty permissions then there is a possible privilege escalation attack vector here as well.

22. WinX menu items

The WinX menu (the right-click Start Menu) contains system tools and as such also represents an attack vector that can be possibly used.

Suffice to say, we want to restrict as many of these lateral movement areas as possible to slow down an attacker or pentester and give us a chance to detect them before they can do damage. But what we also don’t want to do is make our system totally unusable. And this is where we are going to raise the issue of the OneDrive Sync Client. Many of our users are now very dependent on the OneDrive Sync Client for accessing their data, so not affecting this is a key part of this exercise for us.

Blocking the gaps

So let’s start by listing out some of the techniques we are going to use to block out some of these lateral movement opportunities. We have given each technique an acronym so I can easily reference them in a table of results later.

Hide specified drives in My Computer GPO (HSD)

This GPO hides a drive or set of drives from displaying in File Explorer under This PC and also conceals them from the standard dialog boxes. It can be set to pre-determined combinations of drives, or alternatively (more on this later) you can customize it for your own combination. This setting sits in User Configuration | Admin Templates | Windows Components | File Explorer

Prevent access to drives from My Computer GPO (PAD)

This setting is a bit more aggressive than simply hiding the drives within File Explorer – it blocks access to them from File Explorer entirely. Anything within the paths of the drive combination selected will be blocked. As you can imagine, whilst this setting brings a higher level of security with regard to a lot of the lateral movement techniques described earlier, it can also be quite damaging to the user experience. Particularly when we are talking about the OneDrive Sync Client (which by default synchronizes to the C: drive), this setting can be quite obstructive.

As with the setting previously, this can be set to pre-determined combinations or you can create your own. It also sits in User Configuration | Admin Templates | Windows Components | File Explorer

Remove Run from Start Menu GPO (RRC)

This GPO sits in User Configuration | Admin Templates | Start Menu and Taskbar and is a bit more aggressive than the name would suggest. As well as removing the Run command from the Start Menu and preventing it running from the WinX menu, it also prevents using the New Task button in Task Manager, browsing to UNC paths or local drives and folders from the File Explorer or Internet Explorer address bars, and opening the Run menu from Win+R. This setting is quite useful in restricting some of the access but not being as aggressive as PAD (particularly in that this setting allows OneDrive to be accessed!) A problem with it, though, is that the user cannot browse directly to UNC paths. However, they can have shortcuts to UNC paths (either created by themselves, or created dynamically) which will function without issue.

AppLocker GPOs (ALR)

AppLocker is very useful for stopping execution of programs that you do not wish users to be able to run. It can also be combined with the likes of Citrix WEM to extend the functionality further. I like to have AppLocker configured with the default rules which will allow users to execute everything from the Program Files directories and the Windows folder, but blocks anything outside of this (so that programs copied inside their profile, for instance, will not be allowed). One thing to be aware of is you also need to configure the Default Rules for “Packaged app Rules” otherwise you will stop the Start Menu from working!

Blocking local access to the admin shares (BAS)

This is something Dave B focused on and is essential to being able to block out the access of local users to the admin shares (c$, admin$, etc.) For some reason Microsoft decided at some point to allow the locally-logged on user to have access to these shares from a session, which as we have demonstrated already simply opens up a bunch of security holes. The way around it is to import a Registry key via GPP or other method that changes it back to the previous method of operation. Below is an XML import which you can use to paste this directly into GPP

<Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="HKEY_LOCAL_MACHINE"><Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="SYSTEM"><Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="CurrentControlSet"><Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="Services"><Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="lanmanserver"><Collection clsid="{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" name="DefaultSecurity"><Registry clsid="{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}" name="SrvsvcShareAdminConnect" status="SrvsvcShareAdminConnect" image="16" changed="2020-04-16 16:00:56" uid="{EA5041F2-B4B1-E7F2-4D95-9A68136D86AC}"><Properties action="R" displayDecimal="0" default="0" hive="HKEY_LOCAL_MACHINE" key="SYSTEM\CurrentControlSet\Services\lanmanserver\DefaultSecurity" name="SrvsvcShareAdminConnect" type="REG_BINARY" value="010004806400000070000000000000001400000002005000030000000000180003000f00010200000000000520000000200200000000180003000f00010200000000000520000000250200000000180003000f0001020000000000052000000027020000010100000000000512000000010100000000000512000000"/><Filters/></Registry>
					</Collection>
				</Collection>
			</Collection>
		</Collection>
	</Collection>
</Collection>

If you don’t want to use the XML pasting method, then here is a reg file which you can import to get the same effects

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\DefaultSecurity]
"SrvsvcShareAdminConnect"=hex:01,00,04,80,64,00,00,00,70,00,00,00,00,00,00,00,\
  14,00,00,00,02,00,50,00,03,00,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,\
  00,00,05,20,00,00,00,20,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,\
  00,05,20,00,00,00,25,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,00,\
  05,20,00,00,00,27,02,00,00,01,01,00,00,00,00,00,05,12,00,00,00,01,01,00,00,\
  00,00,00,05,12,00,00,00

Be careful when using this, as you would with any Registry change. Once you have enabled this, a user browsing to it from the local machine will need to supply the credentials of a local administrator to access.

Chrome GPO Block access to a list of URLs (CGP)

Chrome has its own sets of ADMX files which you should be leveraging to lock it down and improve performance. The one we are concerned with sits in User Configuration | Admin Templates | Google | Google Chrome and is called Block access to a list of URLs. Configure this with the local drive paths.

Edge and Edge Chromium GPOs (EGP)

The Edge and Edge Chromium GPOs are almost identical to the Chrome ones. They sit in User Config | Admin Templates | Microsoft Edge and the setting has the same name – Block access to a list of URLs

Disable command prompt GPO (CMD)

Disabling the command prompt is an old and well-known GPO that sits in User Configuration | Admin Templates | System. It restricts the execution of the command prompt and .cmd and .bat files as well (if you also disable command prompt script processing). Anyone who still relies on .cmd and .bat files for logon scripts may not be able to do this but if you are still using old-fashioned logon scripts you really need to get away from them.

Disable Registry editing tools GPO (REG)

Again, another tried-and-tested old GPO that restricts access to the Registry editing tools, sitting in User Config | Admin Templates | System. It also offers the option to disable regedit from running silently so it cannot be called from scripts.

FSLogix App Masking (FAM)

FSLogix App Masking is an elegant and reliable way of preventing users accessing executables that they shouldn’t be running. Rather than blocking them like AppLocker, App Masking just makes them disappear, so users can’t even try to run them or even try to copy them to a different location. Normally, I opt to block these executables as a start – powershell.exe, powershell_ise.exe, subst.exe and ftp.exe as they are used within those lateral movement tricks I mentioned earlier. Also don’t forget there are powershell executables in the 64-bit and 32-bit folders!

Edit the WinX menu (EWX)

I wrote a post a while back about how to edit the right-click WinX menu that debuted in Windows 8.1. This often contains shortcuts to system tools. I would recommend editing it to provide a customized menu from within your default profile which can remove these for your users.

Restrict Control Panel and Settings using GPOs (CPS)

These areas of the operating system can be edited using GPOs to ensure that users aren’t able to delve into things they shouldn’t be accessing. For Control Panel, use User Configuration | Admin Templates | Control Panel and choose “Show only specified Control Panel items” (whitelisting being better than blacklisting). Set the applets to those you require your users to have

In order to restrict Settings, you need to get the newest ADMX settings loaded to your central store and go into User Config | Admin Templates | Control Panel and use the setting “Settings Page Visibility” item. You can use ShowOnly: or Hide: to white- or blacklist as appropriate. I recommend using ShowOnly: followed by a semicolon-delimited set of options. If you need to look up all of the available options, use this page (just remove the ms-settings: prefix for each item)

Here’s an example string used here

ShowOnly:printers;mousetouchpad;easeofaccess-audio;easeofaccess-keyboard;easeofaccess-mouse;taskbar;personalization;personalization-background

You should then see the Settings app is much more restricted

Validate installers (VIN)

This is technically part of image management rather than in-session, but it is imperative to make sure that all of your installers deploy to Program Files and not some arbitrary directory path.

Validate services (VSV)

Also part of image management, take time to validate services permissions and whether they have quoted paths or not. GitHub has a script available for remediation of the quoted paths which is very handy.

The OneDrive conundrum

Now, here’s a list of how each of the mitigations works to stop the movement vectors. This is not exact – some of them overlap each other, but this shows the primary functions of each one we have described. However, right at the end we have added an additional consideration – whether the user can access the OneDrive Sync Client folder.

As you can see, the mitigation that covers the most of our bases (the PAD option) and is also the only one to close off common dialog boxes, is also the only one of these that actually prevents us from being able to use the OneDrive Sync Client. What a godawful PITA.

Now, I did originally think we could subst.exe a different drive letter to c:\Users and then use the OneDrive GPO at User Config | Admin Templates | OneDrive “Set the default location for the OneDrive folder”. Setting this to X:\%USERNAME% (assuming x: was the subst-ed drive) would possibly do the trick?

Firstly, though, we have subst.exe blocked. Doh! However there is a very old trick you can do to map a letter to a local drive without using subst.exe. Use the Registry value HKLM\SYSTEM\CurrentControlSet\Session Manager\DOS Devices and add an entry for the drive letter (it adds it for all users, but that isn’t really a huge problem)

When we log on with both this and the OneDrive GPO configured, everything looks great. OneDrive signs in and gets ready to synchronize with the X: drive…. and then…

What an absolute pile of poop OneDrive is! DropBox can synchronize to a network drive, subst-ed drive or reparse point just fine – but OneDrive chokes on it. In fact, OneDrive can’t even synchronize to a secondary hard disk – it is literally hog-tied to the C: drive! Imagine having a 256GB SSD and 1TB of OneDrive – good luck getting that to sync locally. The fact that we are using FSLogix as a remote mounted VHD makes no difference – it is still considered by the OS to be the C: drive. If you want to add your voice to those people who have been waiting five years for Microsoft to add this feature to OneDrive, then feel free to go to the link here and wail into the abyss along with everyone else.

So the basic fact of the matter is that right at this moment in time, if you wish to use the PAD method (Prevent access to drives in My Computer) to restrict users from the C: drive, you can’t use the OneDrive Sync Client. It is one or the other. So we have to come up with a method that restricts everything as much as possible, but doesn’t block out the Sync Client.

My approach

So I went for a bit of a combination of various mitigations and tips and tricks. Here’s what I did!

Firstly, I cracked open my image and validated all of my install paths, services permissions and services paths. I was surprised to find a lot of unquoted service paths but they were easy enough to remediate using the script. With regards to service permissions, all of mine were fine but there is a useful link here for checking them. All of my installer paths checked out fine, even the App-V apps which I was slightly worried about, but it looks like c:\ProgramData\App-V is appropriately secured from an NTFS level.

Next, I made sure all of the following GPO restrictions were scoped to my user base and not to my administrators. You can either do this by Security Filtering (in which case you need to make sure that you add Domain Computers to the access list as well as the target user groups), or by permissions (simply by Denying your administrators group the right to read the configured policies). Personally, I find the first option the best.

I added the Hide specified drives in My Computer GPO for A,B,C and D drives

Now, for the PAD section, we know we can’t restrict the C: drive otherwise we will stop OneDrive from being utilized. However we can restrict access to A, B, D and E. “That’s not an option though!” I hear you say. Correct, from the GPO perspective – but you can use this nifty yet ancient tool called HideCalc to produce a custom value.

Run HideCalc and pick the drives you want to hide. You will see that it tells you the values that you need to set in the Registry

For the PAD function here (which is the one we are looking at), the Registry value to set would be HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoViewOnDrive – for HSD (should you wish to customize this), it is the same key but the value is called NoDrives

You can simply set this in a GPP to enforce your customized setting (the value is most obviously a DWORD)

Next I configured the “Restrict Run command” GPO. I know Dave B said he considers this a substandard user experience but I’m not too sure – if your users have their network paths supplied as shortcuts rather than entering them into the address bar, you should be able to get away with it. Given that I would insist that admins are out of the scope of this GPO, it’s definitely doable. Having said that, if you have users that regularly browse to network paths it might be an idea to pre-create sets of shortcuts for them.

Also, to remove the “Run” command from the WinX menu, consider deleting the Run command (1 – Run.lnk) from %LOCALAPPDATA%\Microsoft\Windows\WinX\Group2 in your default profile. You could also enforce this with a GPP that deletes the aforementioned file.

Next up, AppLocker rules. These are Computer Configuration items but they can be applied on a user or group basis.

Configure your GPO by going to Computer Config | WIndows Settings | Security Settings | Application Control Policies | AppLocker. For each set of rules (Executable, Windows Installer, Script and Packaged App), right-click on the container and choose Create Default Rules. If you forget to do this, as I mentioned earlier, you will break Start Menu functionality.

Unless you have installers that sit outside of the common areas (and if you do, you are vulnerable on point #19 and need to do something about it), this is all the AppLocker configuration required. Now users won’t be able to copy files into their profile and execute them.

The Block Admin Shares (BAS) entry was also done by a GPP. Copying and pasting the XML from the BAS section earlier will create you a ready-made policy. However before doing it I would recommend backing up the existing Registry key to a .reg file.

Next I configured Chrome Group Policies, again very simple

And the same for the Edge/Edge Chromium GPOs

Restrict command prompt and Registry tools were done next, again scoped to the users required and not the administrators. If you’re enabling the “command prompt script processing” piece, then also make sure that you have usrlogon.cmd disabled, otherwise you will generate an error at login.

I then restricted the Control Panel and Settings apps as covered earlier

The next part would be configuring the FSLogix rules. The rules would be configured as below to block powershell.exe, powershell_ise.exe, subst.exe and ftp.exe – as many more can be added as required. The primary usage of this is to block system apps that the user should not be calling.

Some people are a little bit wary of blocking powershell.exe through FSLogix in this way, and I do share this feeling a little bit – some apps call PowerShell under the hood so may not function properly if blocked in this way. If your testing throws up any anomalies, you could remove powershell.exe from the FSLogix Rules and block it through AppLocker or WEM instead. If you’re using AppLocker to block it, though, don’t forget to apply the rule to a group rather than Everyone, or you might block it for your administrators too!

The assignments should be done so that this is NOT applied to the Everyone group and then selectively applied to a group with all of your users in it. This is better for files within the Windows folders so that users like SYSTEM or NetworkService do not lose access.

As well as blocking access to PowerShell I would suggest that you look at PowerShell logging, disabling older versions and running PowerShell Constrained Language Mode. We covered all of these in our presentation and they are written up on Dave’s blog too.

The final part was to configure a customized WinX menu as per my own article, but I opted to skip this step. The reason was because this environment already had a customized WinX menu deployed into the default user profile, and that most of the other mitigations should have restricted them anyway.

Testing

So, now that I had configured all of these settings, it was time to put them to the test. Here’s a quick video I recorded of a machine with all of the relevant settings applied.

We have managed to cut off most of the entry points to the filesystem apart from a couple, which we cannot close off without affecting the OneDrive Sync Client. In OneDrive’s current state, this is as close as I can manage to get to shutting down all of those lateral movement points without affecting usability.

So hopefully this is something that maybe adds a little bit to Dave’s set of original posts and offers a baseline of settings that we can apply to do some securing of our environments.

And as I mentioned, monitoring and baselining is a HUGE part of maintaining an effective balance between security and UX, so stay tuned for more uberAgent goodness later this week.

 1,907 total views,  27 views today

Leave a Reply

Your email address will not be published. Required fields are marked *