Skip to content

Commit

Permalink
v3.0.1-rc28
Browse files Browse the repository at this point in the history
updated the way container status is checked to hopefully reduce rabbitmq errors
  • Loading branch information
its-a-feature committed Jun 29, 2023
1 parent c427a1f commit 301c772
Show file tree
Hide file tree
Showing 17 changed files with 147 additions and 45 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.1-rc28] - 2023-06-29

### Changed

- Updated check for container status to use rabbitmq REST api to port 15672 instead of passively declaring queues
- Updated rabbitmq image to rabbitmq:3-management-alpine to support the above bullet

## [3.0.1-rc26] - 2023-06-26

### Changed
Expand Down
8 changes: 8 additions & 0 deletions MythicReactUI/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.15-rc25] - 2023-06-29

### Changed

- Updated payload building page to not cache query for payload types
- Updated active callbacks table to have a button for adjusting IP instead of right clicking
- Updated c2 profile page's stdout viewer to not cache queries

## [0.1.15-rc24] - 2023-06-21

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ import InfoIcon from '@mui/icons-material/Info';
import { MythicStyledTooltip } from '../../MythicComponents/MythicStyledTooltip';
import {TaskFromUIButton} from './TaskFromUIButton';
import {CallbacksTabsTaskMultipleDialog} from './CallbacksTabsTaskMultipleDialog';
import {CallbacksTabsHideMultipleDialog} from './CallbacksTabsHideMultipleDialog';
import { MythicSelectFromRawListDialog } from '../../MythicComponents/MythicSelectFromListDialog';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';

// callback_stream(batch_size: 1, cursor: {initial_value: {last_checkin: "1970-01-01"}}, where: {id: {_eq: $callback_id}}){
// still have some issues with the stream unfortunately
Expand Down Expand Up @@ -377,7 +377,14 @@ export const CallbacksTableIPCell = ({cellData, rowData, callback_id, updateIPs}
}, [cellData]);
return (
<>
<div onContextMenu={onClick}>{displayIP}</div>
<div style={{display: "flex", alignItems: "center"}}>
{options.length > 1 &&
<MythicStyledTooltip title={"Adjust Displayed"}>
<UnfoldMoreIcon onClick={onClick} style={{paddingTop: "5px", cursor: "pointer"}} />
</MythicStyledTooltip>
}
{displayIP}
</div>
{openPickIP &&
<MythicDialog fullWidth={true} open={openPickIP} onClose={() => {setOpenPickIP(false);}}
innerDialog={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ export function Step2SelectPayloadType(props){
const [fileExtension, setFileExtension] = React.useState('');
const [supportsDynamicLoading, setSupportsDynamicLoading] = React.useState(false);
const [payloadTypeParameters, setSelectedPayloadTypeParameters] = React.useState([]);
const { loading, error, data } = useQuery(GET_Payload_Types, {variables:{os: props.buildOptions },
const { loading, error, data } = useQuery(GET_Payload_Types,
{variables:{os: props.buildOptions },
fetchPolicy: "no-cache",
onCompleted: data => {
if(data.payloadtype.length > 0){
if(props.prevData !== undefined && props.prevData.os === props.buildOptions){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export function Step2SelectPayloadType(props){
const [selectedPayloadTypeID, setSelectedPayloadTypeID] = React.useState(0);
const [fileExtension, setFileExtension] = React.useState('');
const [payloadTypeParameters, setSelectedPayloadTypeParameters] = React.useState([]);
const { loading, error, data } = useQuery(GET_Payload_Types, {variables:{os: props.buildOptions},
const { loading, error, data } = useQuery(GET_Payload_Types,
{variables:{os: props.buildOptions},
fetchPolicy: "no-cache",
onCompleted: data => {
if(data.payloadtype.length > 0){
if(props.prevData !== undefined && props.prevData.os === props.buildOptions){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import {useQuery, gql} from '@apollo/client';
import LinearProgress from '@mui/material/LinearProgress';
import AceEditor from 'react-ace';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-monokai';
import 'ace-builds/src-noconflict/theme-xcode';
import {useTheme} from '@mui/material/styles';
import {snackActions} from "../../utilities/Snackbar";

const getProfileOutputQuery = gql`
query getProfileOutput($id: Int!) {
Expand All @@ -24,20 +24,29 @@ query getProfileOutput($id: Int!) {

export function C2ProfileOutputDialog(props) {
const theme = useTheme();
const { loading, error, data } = useQuery(getProfileOutputQuery, {
const [outputData, setOutputData] = React.useState("Waiting 3s for data...");
useQuery(getProfileOutputQuery, {
variables: {id: props.profile_id},
onCompleted: data => {
//console.log("completed", data.getProfileOutput.output)
console.log("completed")
if(data.getProfileOutput.status === "success"){
if(data.getProfileOutput.output.length === 0){
setOutputData("No data from server");
} else {
setOutputData(data.getProfileOutput.output);
}

} else {
snackActions.error(data.getProfileOutput.error);
}

},
onError: data => {
snackActions.error(data.message);
console.log(data);
},
fetchPolicy: "network-only"
fetchPolicy: "no-cache"
});
if (loading) {
return <LinearProgress />;
}
if (error) {
console.error(error);
return <div>Error! {error.message}</div>;
}

return (
<React.Fragment>
Expand All @@ -53,7 +62,7 @@ export function C2ProfileOutputDialog(props) {
showGutter={true}
height={"100px"}
highlightActiveLine={true}
value={data.getProfileOutput.output}
value={outputData}
width={"100%"}
minLines={2}
maxLines={50}
Expand Down
4 changes: 2 additions & 2 deletions MythicReactUI/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import MessageTypes from 'subscriptions-transport-ws/dist/message-types';
import jwt_decode from 'jwt-decode';
import {meState} from './cache';

export const mythicVersion = "3.0.1-rc25";
export const mythicUIVersion = "0.1.15-rc24";
export const mythicVersion = "3.0.1-rc28";
export const mythicUIVersion = "0.1.15-rc25";

let fetchingNewToken = false;

Expand Down
6 changes: 4 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
The following the table details the supported versions of Mythic.

| Version | Supported |
| ------- | ------------------ |
| 2.3.7 | :white_check_mark: |
|---------| ------------------ |
| 3.0.0 | :white_check_mark: |
| 2.3.13 | :x: |
| 2.3.9 | :x: |
| < 2.3.0 | :x: |


Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.1-rc27
3.0.1-rc28
94 changes: 79 additions & 15 deletions mythic-docker/src/rabbitmq/check_container_status.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package rabbitmq

import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/its-a-feature/Mythic/grpc"
"github.com/its-a-feature/Mythic/utils"
"io"
"net/http"
"time"

"github.com/its-a-feature/Mythic/database"
Expand Down Expand Up @@ -61,27 +66,91 @@ func initializeContainers() {
}
}
}

var tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
MaxIdleConns: 10,
MaxConnsPerHost: 10,
//IdleConnTimeout: 1 * time.Nanosecond,
}
var httpClient = &http.Client{
Timeout: 5 * time.Second,
Transport: tr,
}

type rabbitmqAPIQuery struct {
FilteredCount int `json:"filtered_count" mapstructure:"filtered_count"`
ItemCount int `json:"item_count" mapstructure:"item_count"`
Items []map[string]interface{} `json:"items" mapstructure:"items"`
Page int `json:"page" mapstructure:"page"`
PageCount int `json:"page_count" mapstructure:"page_count"`
PageSize int `json:"page_size" mapstructure:"page_size"`
TotalCount int `json:"total_count" mapstructure:"total_count"`
}

func checkContainerStatus() {
// get all queues from rabbitmq
// http://rabbitmq_user:rabbitmq_password@rabbitmq_host:15672/rabbitmq/api/queues/mythic_vhost
rabbitmqReqURL := fmt.Sprintf("http://%s:%s@%s:15672/api/queues/mythic_vhost?use_regex=true&page=1&page_size=500&name=%s",
utils.MythicConfig.RabbitmqUser, utils.MythicConfig.RabbitmqPassword, utils.MythicConfig.RabbitmqHost,
fmt.Sprintf("(.%%2A_%s|.%%2A_%s)", PT_BUILD_ROUTING_KEY, C2_RPC_START_SERVER_ROUTING_KEY))
go checkContainerStatusAddPT()
go checkContainerStatusAddC2()
go checkContainerStatusAddTR()
go initializeContainers()
for {
time.Sleep(CHECK_CONTAINER_STATUS_DELAY)
rabbitmqReq, err := http.NewRequest("GET", rabbitmqReqURL, nil)
if err != nil {
logging.LogError(err, "Failed to generate http request to fetch queues from rabbitmq")
continue
}
rabbitmqResponse, err := httpClient.Do(rabbitmqReq)
if err != nil {
logging.LogError(err, "Failed to fetch queues from rabbitmq")
continue
}
if rabbitmqResponse.StatusCode != 200 {
logging.LogError(nil, "Failed to get a good status code from rabbitmq",
"status_code", rabbitmqResponse.StatusCode, "status", rabbitmqResponse.Status)
continue
}
rabbitmqBody, err := io.ReadAll(rabbitmqResponse.Body)
if err != nil {
logging.LogError(err, "Failed to read body of message from rabbitmq")
rabbitmqResponse.Body.Close()
continue
}
rabbitmqResponse.Body.Close()

rabbitmqQueues := rabbitmqAPIQuery{}
err = json.Unmarshal(rabbitmqBody, &rabbitmqQueues)
if err != nil {
logging.LogError(err, "Failed to convert rabbitmq response into list of dictionaries")
continue
}
//logging.LogInfo("got message from rabbitmq", "queue body", rabbitmqQueues)
existingQueues := make([]string, len(rabbitmqQueues.Items))
for index, queue := range rabbitmqQueues.Items {
if queueName, ok := queue["name"]; !ok {
logging.LogError(nil, "no 'name' field in queue information from rabbitmq")
} else {
existingQueues[index] = queueName.(string)
//logging.LogInfo("found queue", "queue", queueName)
}
}

// loop through payload types
for container := range payloadTypesToCheck {
//logging.LogDebug("checking container", "container", container)
// check that a container is online
running, err := RabbitMQConnection.CheckPayloadTypeContainerExists(payloadTypesToCheck[container].Name)
//logging.LogInfo("checking container running", "container", container, "running", running, "current_running", payloadTypesToCheck[container].ContainerRunning)
if err != nil {
logging.LogError(err, "Failed to check for payloadtype container existence")
} else if running != payloadTypesToCheck[container].ContainerRunning {
running := utils.SliceContains(existingQueues, GetPtBuildRoutingKey(payloadTypesToCheck[container].Name))
if running != payloadTypesToCheck[container].ContainerRunning {
if entry, ok := payloadTypesToCheck[container]; ok {
entry.ContainerRunning = running
if _, err = database.DB.NamedExec(`UPDATE payloadtype SET
container_running=:container_running, deleted=false
WHERE id=:id`, entry,
if _, err = database.DB.NamedExec(`UPDATE payloadtype SET
container_running=:container_running, deleted=false
WHERE id=:id`, entry,
); err != nil {
logging.LogError(err, "Failed to set container running status", "container_running", payloadTypesToCheck[container].ContainerRunning, "container", container)
} else {
Expand All @@ -97,19 +166,15 @@ func checkContainerStatus() {
} else {
logging.LogError(nil, "Failed to get payload type from map for updating running status")
}

}

}
// loop through c2 profiles
for container := range c2profilesToCheck {
// check that a container is online
//logging.LogDebug("checking container", "container", container)
running, err := RabbitMQConnection.CheckC2ProfileContainerExists(container)
running := utils.SliceContains(existingQueues, GetC2RPCStartServerRoutingKey(c2profilesToCheck[container].Name))
//logging.LogInfo("checking container running", "container", container, "running", running, "current_running", c2profilesToCheck[container].ContainerRunning)
if err != nil {
logging.LogError(err, "Failed to check for c2 container existence")
} else if running != c2profilesToCheck[container].ContainerRunning {
if running != c2profilesToCheck[container].ContainerRunning {
if entry, ok := c2profilesToCheck[container]; ok {
entry.ContainerRunning = running
if _, err = database.DB.NamedExec(`UPDATE c2profile SET
Expand All @@ -129,7 +194,6 @@ func checkContainerStatus() {
} else {
logging.LogError(nil, "Failed to get c2 profile from map for updating running status")
}

}
}
// loop through translation containers
Expand Down
6 changes: 3 additions & 3 deletions mythic-react-docker/mythic/public/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"files": {
"main.css": "/new/static/css/main.4722e92b.css",
"main.js": "/new/static/js/main.cec2d3ce.js",
"main.js": "/new/static/js/main.472aed0e.js",
"static/media/mythic.svg": "/new/static/media/mythic.7189479fdfbd51ae729872ce2cb98784.svg",
"static/media/mythic_red_small.svg": "/new/static/media/mythic_red_small.793b41cc7135cdede246661ec232976b.svg",
"index.html": "/new/index.html",
"main.4722e92b.css.map": "/new/static/css/main.4722e92b.css.map",
"main.cec2d3ce.js.map": "/new/static/js/main.cec2d3ce.js.map"
"main.472aed0e.js.map": "/new/static/js/main.472aed0e.js.map"
},
"entrypoints": [
"static/css/main.4722e92b.css",
"static/js/main.cec2d3ce.js"
"static/js/main.472aed0e.js"
]
}
2 changes: 1 addition & 1 deletion mythic-react-docker/mythic/public/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/new/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="apple-touch-icon" href="/new/logo192.png"/><link rel="manifest" href="/new/manifest.json"/><title>Mythic</title><script defer="defer" src="/new/static/js/main.cec2d3ce.js"></script><link href="/new/static/css/main.4722e92b.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/new/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="apple-touch-icon" href="/new/logo192.png"/><link rel="manifest" href="/new/manifest.json"/><title>Mythic</title><script defer="defer" src="/new/static/js/main.472aed0e.js"></script><link href="/new/static/css/main.4722e92b.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
3 changes: 3 additions & 0 deletions mythic-react-docker/mythic/public/static/js/main.472aed0e.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions mythic-react-docker/mythic/public/static/js/main.cec2d3ce.js

This file was deleted.

3 changes: 2 additions & 1 deletion rabbitmq-docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
FROM rabbitmq:3-alpine
#FROM rabbitmq:3-alpine
FROM rabbitmq:3-management-alpine
ADD rabbitmq.conf /etc/rabbitmq/rabbitmq.conf

0 comments on commit 301c772

Please sign in to comment.