Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.7.1 into main #91

Merged
merged 11 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading