Skip to content

Commit

Permalink
Merge pull request #91 from BC-SECURITY/release/2.7.1
Browse files Browse the repository at this point in the history
v2.7.1 into main
  • Loading branch information
vinnybod authored Dec 4, 2023
2 parents aba80d4 + 3bb9c38 commit fff262a
Show file tree
Hide file tree
Showing 74 changed files with 1,326 additions and 1,470 deletions.
42 changes: 41 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,44 @@ 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).

**Added** for new features.
**Changed** for changes in existing functionality.
**Deprecated** for soon-to-be removed features.
**Removed** for now removed features.
**Fixed** for any bug fixes.
**Security** in case of vulnerabilities.

## [Unreleased]

## [2.7.1] - 2023-12-03

### Changed

- Remove Interactive Agent Shell from README

## [2.7.0] - 2023-11-15

### Added

- Add agent dropdown when Agent is a field in a form
- Add auto-refresh on Agents / Agents Tasks page
- Add auto-refresh on Plugins Tasks page

### Changed

- Migrate from Vuex to Pinia

### Fixed

- Fix form dropdowns getting out of sync with reality by refreshing the store on load
- Making edits to an Agent on the 'View' tab now properly updates the parent Agent page
- Updating an agent's name no longer refreshes the page on submit
- After updating a stager, the download/clipboard of the stager now reflects the changes without requiring the page to be reloaded

### Removed

- Remove unused AgentCommandViewer component

## [2.6.1] - 2023-09-25

- Make notification bell menu scrollable with a max height
Expand Down Expand Up @@ -307,7 +343,11 @@ Including but not limited to:

- Initial Release

[Unreleased]: https://github.com/BC-SECURITY/Starkiller-Sponsors/compare/v2.6.1...HEAD
[Unreleased]: https://github.com/BC-SECURITY/Starkiller-Sponsors/compare/v2.7.1...HEAD

[2.7.1]: https://github.com/BC-SECURITY/Starkiller-Sponsors/compare/v2.7.0...v2.7.1

[2.7.0]: https://github.com/BC-SECURITY/Starkiller-Sponsors/compare/v2.6.1...v2.7.0

[2.6.1]: https://github.com/BC-SECURITY/Starkiller-Sponsors/compare/v2.6.0...v2.6.1

Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ At the moment, the extra Starkiller sponsorship features include:

<div align="left"><img width="800" src="https://user-images.githubusercontent.com/9831420/216792129-5b0fed82-b209-48cb-9a43-eeb3e69c7229.gif"></div>

## Interactive agent shell

<div align="left"><img width="800" src="https://user-images.githubusercontent.com/9831420/104983879-e37fc700-59ca-11eb-9c90-bd2d166c4ac5.gif"></div>

## Process Browser

<div align="left"><img width="800" src="https://user-images.githubusercontent.com/9831420/131264080-0264558d-59c4-44d9-8dae-7b518c47a9cb.gif"></div>
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "starkiller",
"version": "2.6.1",
"version": "2.7.1",
"private": true,
"scripts": {
"dev": "vite",
Expand All @@ -18,6 +18,8 @@
"axios": "^0.24.0",
"lodash.debounce": "^4.0.8",
"moment": "^2.29.1",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"portal-vue": "^2.1.7",
"qs": "^6.10.3",
"semver": "^7.3.5",
Expand All @@ -28,9 +30,7 @@
"vue": "2.7",
"vue-beautiful-chat": "^2.5.0",
"vue-router": "^3.5.1",
"vuetify": "^2.6.0",
"vuex": "^3.6.2",
"vuex-persistedstate": "^3.0.1"
"vuetify": "^2.6.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
Expand All @@ -42,6 +42,6 @@
"prettier": "^3.0.2",
"sass": "~1.32",
"unplugin-vue-components": "^0.22.12",
"vite": "^3"
"vite": "^4"
}
}
21 changes: 10 additions & 11 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div id="app">
<v-app :dark="isDarkMode">
<v-app :dark="darkMode">
<side-nav v-if="isLoggedIn && !hideSideBar" />
<confirm ref="confirm" />
<socket-notifications
Expand Down Expand Up @@ -70,13 +70,14 @@
<script>
import Vue from "vue";
import semver from "semver";
import { mapGetters, mapState } from "vuex";
import { mapState } from "pinia";
import SideNav from "@/components/SideNav.vue";
import Confirm from "@/components/Confirm.vue";
import SocketNotifications from "@/components/SocketNotifications.vue";
import StarkillerSnackbar from "@/components/StarkillerSnackbar.vue";
import NotificationBell from "@/components/NotificationBell.vue";
import { useApplicationStore } from "@/stores/application-module";
export default {
name: "App",
Expand All @@ -88,14 +89,12 @@ export default {
StarkillerSnackbar,
},
computed: {
...mapGetters({
isLoggedIn: "application/isLoggedIn",
isDarkMode: "application/isDarkMode",
}),
...mapState({
empireVersion: (state) => state.application.empireVersion,
connectionError: (state) => state.application.connectionError,
}),
...mapState(useApplicationStore, [
"isLoggedIn",
"darkMode",
"empireVersion",
"connectionError",
]),
isLoginPage() {
return this.$route.name === "home";
},
Expand All @@ -114,7 +113,7 @@ export default {
}
},
},
isDarkMode: {
darkMode: {
immediate: true,
handler(val) {
if (val === true) {
Expand Down
9 changes: 4 additions & 5 deletions src/api/axios-instance.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import axios from "axios";

// I don't like this cyclic dependency, but struggling to find a better way atm.
import store from "@/store/index";
import { useApplicationStore } from "@/stores/application-module";

// eslint-disable-next-line import/no-mutable-exports
export let axiosInstance = null;
Expand All @@ -20,12 +18,13 @@ export function setInstance(url, token) {
(response) => response,
(err) => {
if (!err?.response) {
store.dispatch("application/connectionError");
useApplicationStore().connectionError += 1;
}

if (err?.response?.status === 401 || err?.response?.status === 403) {
store.dispatch("application/logout");
useApplicationStore().logout();
}

return Promise.reject(err);
},
);
Expand Down
1 change: 0 additions & 1 deletion src/api/bypass-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { axiosInstance as axios, handleError } from "@/api/axios-instance";
/**
* Returns a full list of bypasses.
*/
// eslint-disable-next-line import/prefer-default-export
export function getBypasses() {
return axios
.get("/bypasses")
Expand Down
25 changes: 18 additions & 7 deletions src/components/Chat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
</template>

<script>
import { mapState } from "vuex";
import { useUserStore } from "@/stores/user-module";
import { useApplicationStore } from "@/stores/application-module";
export default {
name: "Chat",
Expand All @@ -66,11 +67,21 @@ export default {
};
},
computed: {
...mapState({
me: (state) => state.application.user.username,
allUsers: (state) => state.user.users,
darkMode: (state) => state.application.darkMode,
}),
userStore() {
return useUserStore();
},
allUsers() {
return this.userStore.users;
},
applicationStore() {
return useApplicationStore();
},
me() {
return this.applicationStore.user.username;
},
darkMode() {
return this.applicationStore.darkMode;
},
colors() {
if (this.darkMode) {
return {
Expand Down Expand Up @@ -107,7 +118,7 @@ export default {
},
},
mounted() {
this.$store.dispatch("user/getUsers");
this.userStore.getUsers();
this.socket.on("chat/join", (data) => {
if (!this.isChatOpen) this.newMessagesCount++;
const message = { type: "system", data: { text: data.message } };
Expand Down
11 changes: 5 additions & 6 deletions src/components/ClickToEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
dense
required
@blur="update"
@keyup.enter="update"
@keyup.enter.native="update"
/>
</template>
<span v-else class="ml-3">
Expand All @@ -97,8 +97,9 @@
</template>

<script>
import { mapGetters } from "vuex";
import { mapState } from "pinia";
import moment from "moment";
import { useApplicationStore } from "@/stores/application-module";
export default {
components: {},
Expand Down Expand Up @@ -145,9 +146,7 @@ export default {
dirty() {
return this.original !== this.internalValue;
},
...mapGetters({
isDarkMode: "application/isDarkMode",
}),
...mapState(useApplicationStore, ["darkMode"]),
},
watch: {
internalValue(val) {
Expand Down Expand Up @@ -197,7 +196,7 @@ export default {
},
getColClass() {
if (this.editing === false && this.editable === true) {
if (this.isDarkMode) {
if (this.darkMode) {
return "column-not-editing-dark";
}
return "column-not-editing";
Expand Down
11 changes: 11 additions & 0 deletions src/components/DynamicFormInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@
:label="name"
/>

<v-autocomplete
v-else-if="name === 'Agent'"
v-model="internalValue"
:items="suggestedValues"
:label="name"
outlined
dense
item-value="session_id"
item-text="name"
/>

<v-autocomplete
v-else-if="name === 'CredID'"
v-model="internalValue"
Expand Down
62 changes: 43 additions & 19 deletions src/components/GeneralForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@

<script>
import Vue from "vue";
import { mapGetters } from "vuex";
import { useListenerStore } from "@/stores/listener-module";
import { useBypassStore } from "@/stores/bypass-module";
import { useCredentialStore } from "@/stores/credential-module";
import { useMalleableProfileStore } from "@/stores/malleable-module";
import { useAgentStore } from "@/stores/agent-module";
import DynamicFormInput from "./DynamicFormInput.vue";
export default {
Expand Down Expand Up @@ -73,12 +77,36 @@ export default {
};
},
computed: {
...mapGetters({
listeners: "listener/listenerNames",
bypasses: "bypass/bypassNames",
malleableProfiles: "malleable/profileNames",
credentials: "credential/credentials",
}),
agentStore() {
return useAgentStore();
},
listenerStore() {
return useListenerStore();
},
bypassStore() {
return useBypassStore();
},
credentialStore() {
return useCredentialStore();
},
malleableProfileStore() {
return useMalleableProfileStore();
},
agents() {
return this.agentStore.agents;
},
listeners() {
return this.listenerStore.listenerNames;
},
bypasses() {
return this.bypassStore.bypassNames;
},
credentials() {
return this.credentialStore.credentials;
},
malleableProfiles() {
return this.malleableProfileStore.profileNames;
},
/**
* Fields that go in the "Optional" section
*/
Expand Down Expand Up @@ -165,21 +193,17 @@ export default {
},
},
mounted() {
if (this.listeners?.length === 0) {
this.$store.dispatch("listener/getListeners");
}
if (this.bypasses?.length === 0) {
this.$store.dispatch("bypass/getBypasses");
}
if (this.malleableProfiles?.length === 0) {
this.$store.dispatch("malleable/getMalleableProfiles");
}
if (this.credentials?.length === 0) {
this.$store.dispatch("credential/getCredentials");
}
this.agentStore.getAgents();
this.listenerStore.getListeners();
this.bypassStore.getBypasses();
this.malleableProfileStore.getMalleableProfiles();
this.credentialStore.getCredentials();
},
methods: {
suggestedValuesForField(field) {
if (field.name === "Agent") {
return this.agents;
}
if (["Listener", "RedirectListener"].includes(field.name)) {
return this.listeners;
}
Expand Down
Loading

0 comments on commit fff262a

Please sign in to comment.