Mythic Documentation
Version 3.3
Version 3.3
  • Mythic
  • Operators
  • Installation
    • Connecting
    • A note about containers
    • Offline Installation
    • Updating Mythic
  • Internal Documentation
  • Quick Usage
  • Operational Pieces
    • MITRE ATT&CK
    • Operations
    • Browser Scripts
    • Active Callbacks
    • Files
    • Search
    • File Browser
    • Socks Proxy
    • Credentials
    • Comments
    • Tags
    • Expanded Callbacks
    • Screenshots
    • Event Feed
    • Understanding Commands
      • Basic Information
      • Parameters
      • MITRE ATT&CK in Commands
    • Payload Types
      • Containers
    • C2 Profiles
      • C2 Server Utilities
      • Egress vs P2P
      • HTTP
      • dynamicHTTP
      • Save Parameters
    • API Tokens
  • Message Flow
    • Building Payloads
    • Agent Sends Message
    • File Upload Mythic->Agent
    • File Download Agent->Mythic
    • P2P Messages
    • Operator Submits Tasking
  • Database Schema
  • Reporting
    • Artifacts
    • MITRE ATT&CK
    • Reports
  • Scripting
  • Presentations / Webinars
  • Common Errors
  • MythicTips
  • Customizing
    • Customizing Public Agent
    • Hooking Features
      • Actions
      • Linking Agents
        • P2P Connections
      • Process Browser
      • Artifacts
      • Credentials
      • File Downloads (Agent -> Mythic)
      • File Uploads (Mythic -> Agent)
      • Screenshots
      • Add / Remove Commands
      • Keylog
      • File Browser
      • Tokens
      • Alerts
      • SOCKS
      • RPFWD
      • Interactive Tasking
      • Task Status
      • OnContainerStart
    • 1. Payload Type Development
      • 2. Payload Type Definition
        • Container Syncing
        • Turning a VM into a Container
      • 3. Adding Commands
        • Commands
      • 4. Create Tasking & Comms Format
        • Agent Messages
          • 1. Agent Message Format
          • 2. Checkin
          • 3. Get Tasking
          • 4. Submitting Responses
          • 5. SOCKS
          • 6. Reverse Port Forward
          • 7. Peer-to-peer messages
          • 8. Interactive Tasking
      • 5. MythicRPC
      • 6. Browser Scripting
      • 7. Dynamic Parameter Values
      • 8. Sub-tasking / Task Callbacks
      • 9. OPSEC Checking
      • 10. Translation Containers
      • 11. Process Response
      • 12 TypedArray Parse Function
      • 13. SOCKS
      • 14. Reverse PortFwd
      • 15. Interactive Tasking
    • 2. C2 Development
      • Docker & Server Config
        • 1. Docker Containers
        • 2. Configuration Files
        • 3. OPSEC Checks
        • 4. Configuration Checks
        • 5. Sample Message
        • 6. File Hosting
        • 7. Redirect Rules
        • 8. Get IOC
        • 9. Push C2
    • 3. Consuming Containers
      • Webhooks
      • Logging
      • Eventing
        • Operator Context (run_as)
        • Workflow Triggers
        • Steps
      • Auth
    • 4. Extending Agent Commands
    • Mythic UI Development
  • Common Questions and Answers
    • FAQ / Troubleshooting Tips
    • Change Log
    • Tip of the Week
  • Updating
    • Mythic 2.1 -> 2.2 Updates
      • Agents 2.1.* -> 2.2.8
        • MythicRPC
    • Mythic 2.2 -> 2.3 Updates
      • Agents 2.2 -> 2.3
    • Mythic 2.3 -> 3.0 Updates
      • Agents 2.3 -> 3.0
    • Mythic 3.2->3.3 Updates
Powered by GitBook
On this page
  • Auth Structure
  • Auth Functionality
  • IDP SSO Services
  • Non-IDP SSO Services

Was this helpful?

Export as PDF
  1. Customizing
  2. 3. Consuming Containers

Auth

PreviousStepsNext4. Extending Agent Commands

Last updated 10 months ago

Was this helpful?

Auth Structure

Auth containers allow you to extend Mythic's login capabilities by offloading the check from Mythic's salted + hashed database password to something else. This can either be towards an Identity Provider (IDP) like Microsoft ADFS (SSO), or towards a non-identity provider/SSO check (like attempted auth to an LDAP service).

type AuthDefinition struct {
	Name                  string   `json:"name"`
	Description           string   `json:"description"`
	IDPServices           []string `json:"idp_services"`
	NonIDPServices        []string `json:"non_idp_services"`
	GetIDPMetadata        func(GetIDPMetadataMessage) GetIDPMetadataMessageResponse
	GetIDPRedirect        func(GetIDPRedirectMessage) GetIDPRedirectMessageResponse
	ProcessIDPResponse    func(ProcessIDPResponseMessage) ProcessIDPResponseMessageResponse
	GetNonIDPMetadata     func(GetNonIDPMetadataMessage) GetNonIDPMetadataMessageResponse
	GetNonIDPRedirect     func(GetNonIDPRedirectMessage) GetNonIDPRedirectMessageResponse
	ProcessNonIDPResponse func(ProcessNonIDPResponseMessage) ProcessNonIDPResponseMessageResponse
	// Subscriptions - don't bother here, this will be auto filled out on syncing
	Subscriptions            []string                                                                                  `json:"subscriptions"`
	OnContainerStartFunction func(sharedStructs.ContainerOnStartMessage) sharedStructs.ContainerOnStartMessageResponse `json:"-"`
}

for example:

func Initialize() {
    authName := "MyAuthProvider"
    myAuth := authstructs.AuthDefinition{
       Name:           authName,
       Description:    "A custom SSO auth provider for ADFS",
       IDPServices:    []string{"ADFS"},
       NonIDPServices: []string{"LDAP"},
       OnContainerStartFunction: func(message sharedStructs.ContainerOnStartMessage) sharedStructs.ContainerOnStartMessageResponse {
          logging.LogInfo("started", "inputMsg", message)
          return sharedStructs.ContainerOnStartMessageResponse{}
       },
       GetIDPMetadata: func(message authstructs.GetIDPMetadataMessage) authstructs.GetIDPMetadataMessageResponse {
          response := authstructs.GetIDPMetadataMessageResponse{
             Success: false,
          }
          err := initializeSAMLSP(authName, message.ServerName)
          if err != nil {
             response.Error = err.Error()
             return response
          }
          buf, err := xml.MarshalIndent(samlSP.ServiceProvider.Metadata(), "", " ")
          if err != nil {
             response.Error = err.Error()
             return response
          }
          response.Success = true
          response.Metadata = string(buf)
          return response
       },
...
}

Auth Functionality

There are two forms of auth containers - Identity Provider (IDP) SSO Services and Non-IDP checks. The IDP and NonIDP Services are available as options in the Logon UI page as long as the containers are online. If the auth container goes offline, then the option will disappear from the Logon page and you will have to fallback to the normal Mythic logon procedures.

IDP SSO Services

In these cases we are going to use the auth container to forward Mythic to a remote, SSO Identity Provider. This tends to have a few components:

  • The SSO Identity Provider needs to get some sort of metadata from the auth container to register it as a trusted partner (i.e. GetIDPMetadata)

  • The user needs to be redirected to this IDP to kick off the auth flow (username/password, MFA, duo prompts, etc) (i.e. GetIDPRedirect)

  • After the IDP has determined if you're authorized or not, the result needs to be POSTed back to Mythic (and thus to the auth container) (i.e. ProcessIDPResponse). The end result here has to return a message back to Mythic to inform Mythic of two things:

    • was the authentication successful or not

    • what is the email associated with the user that just authenticated

The IDPServices array identifies which options are displayed to the user when they try to log in:

IDPServices:    []string{"ADFS"},

Selecting the ADFS - MyAuthProvder kicks off a request to the GetIDPRedirect function.

Non-IDP SSO Services

The flow here is almost exactly the same as the IDP SSO Services, but instead of IDP, we have NonIDP everywhere. However, since we're not redirecting the user to an SSO service, we need to specify what information we need the user to provide. The GetNonIDPRedirect returns an array of fields that we want the user to specify:

GetNonIDPRedirect: func(message authstructs.GetNonIDPRedirectMessage) authstructs.GetNonIDPRedirectMessageResponse {
    return authstructs.GetNonIDPRedirectMessageResponse{
       Success:       true,
       RequestFields: []string{"username", "password", "OTP"},
    }
},

This generates three fields in Mythic's logon page for username, password, and OTP. Once the user provides their data and click "login", then the containers ProcessNonIDPResponse function is called.

Just like in the IDP SSO Services function, at the end of this we need to return if auth was successful or not and the email of the user that was authenticated.