Skip to content

Commit

Permalink
Add webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
rasta-mouse committed Apr 30, 2023
1 parent 0b361e9 commit dd118fb
Show file tree
Hide file tree
Showing 29 changed files with 884 additions and 29 deletions.
6 changes: 6 additions & 0 deletions Client/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@ public App()
InitializeComponent();

MainPage = new MainPage();
MainPage.Disappearing += MainPageOnDisappearing;
}

private static void MainPageOnDisappearing(object sender, EventArgs e)
{
SecureStorage.Remove("nick");
}
}
77 changes: 77 additions & 0 deletions Client/Components/Webhooks/CreateWebhook.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@using Client.Models.Events
@using SharpC2.API.Requests

@inject SharpC2Api Api

<MudDialog>
<DialogContent>
<MudForm @ref="_form" @bind-IsValid="@_success">

<MudItem Class="my-4">
<MudSelect T="WebhookConsumer" Label="Consumer" Variant="Variant.Outlined" @bind-Value="@_consumer">
<MudSelectItem T="WebhookConsumer" Value="WebhookConsumer.SLACK"/>
<MudSelectItem T="WebhookConsumer" Value="WebhookConsumer.CUSTOM"/>
</MudSelect>
</MudItem>

<MudItem Class="my-4">
<MudTextField T="string" @bind-Value="_name" Label="Name" Required="true"
RequiredError="Name is required" Immediate="@true"/>
</MudItem>

<MudItem Class="my-4">
<MudSelect T="EventType" Label="Event" Variant="Variant.Outlined" @bind-Value="@_event">
<MudSelectItem T="EventType" Value="EventType.USER_AUTH" />
<MudSelectItem T="EventType" Value="EventType.WEB_LOG" />
</MudSelect>
</MudItem>

<MudItem Class="my-4">
<MudTextField T="string" @bind-Value="_url" Label="URL" Required="true"
RequiredError="URL is required" Immediate="@true"/>
</MudItem>

</MudForm>
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel">Cancel</MudButton>
<MudButton Color="Color.Primary" OnClick="Submit">Save</MudButton>
</DialogActions>
</MudDialog>

@code {

[CascadingParameter]
public MudDialogInstance MudDialog { get; set; }

private MudForm _form;
private bool _success;

private string _name;
private WebhookConsumer _consumer;
private EventType _event;
private string _url;

private async Task Submit()
{
if (!_success)
{
await _form.Validate();
return;
}

var request = new WebhookRequest
{
Name = _name,
Consumer = (int)_consumer,
Event = (int)_event,
Url = _url
};

await Api.CreateWebhook(request);
MudDialog.Close(DialogResult.Ok(true));
}

private void Cancel()
=> MudDialog.Cancel();
}
33 changes: 33 additions & 0 deletions Client/Models/Webhooks/SharpC2Webhook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Client.Models.Events;
using SharpC2.API.Responses;

namespace Client.Models.Webhooks;

public sealed class SharpC2Webhook
{
public string Id { get; set; }
public string Name { get; set; }
public WebhookConsumer Consumer { get; set; }
public EventType Event { get; set; }
public string Url { get; set; }

public static implicit operator SharpC2Webhook(WebhookResponse response)
{
return response is null
? null
: new SharpC2Webhook
{
Id = response.Id,
Name = response.Name,
Consumer = (WebhookConsumer)response.Consumer,
Event = (EventType)response.Event,
Url = response.Url
};
}
}

public enum WebhookConsumer
{
SLACK,
CUSTOM
}
88 changes: 88 additions & 0 deletions Client/Pages/Webhooks.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
@attribute [Authorize]
@page "/webhooks"
@using Client.Components.Webhooks

@inject SharpC2Api Api
@inject SharpC2Hub Hub
@inject IDialogService Dialogs

<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge">
<MudTable Items="@_webhooks" Hover="true" Loading="@_loading" LoadingProgressColor="Color.Info">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Consumer</MudTh>
<MudTh>Event</MudTh>
<MudTh>URL</MudTh>
<MudTh></MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Name">@context.Name</MudTd>
<MudTd DataLabel="Consumer">@context.Consumer</MudTd>
<MudTd DataLabel="Event">@context.Event</MudTd>
<MudTd DataLabel="URL">@context.Url</MudTd>
<MudTd>
<MudTooltip Text="Delete">
<MudIconButton Icon="@Icons.Material.Filled.DeleteForever" Size="Size.Medium"
Color="@Color.Error" OnClick="@(async () => await DeleteWebhook(context))"/>
</MudTooltip>
</MudTd>
</RowTemplate>
<NoRecordsContent>
No Webhooks
</NoRecordsContent>
</MudTable>

<MudTooltip Text="Add Webhook">
<MudFab Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" Size="Size.Medium" Class="mt-4"
OnClick="OpenCreateWebhook"/>
</MudTooltip>

</MudContainer>

@code {

private bool _loading = true;
private readonly List<SharpC2Webhook> _webhooks = new();

protected override void OnInitialized()
{
Hub.WebhookCreated += OnWebhookCreated;
Hub.WebhookDeleted += OnWebhookDeleted;
}

protected override async Task OnInitializedAsync()
{
var webhooks = await Api.GetWebhooks();

_webhooks.AddRange(webhooks);
_loading = false;
}

private async Task DeleteWebhook(SharpC2Webhook webhook)
{
await Api.DeleteWebhook(webhook.Name);
}

private async Task OpenCreateWebhook()
{
var options = new DialogOptions { FullWidth = true };
await Dialogs.ShowAsync<CreateWebhook>("", options);
}

private async Task OnWebhookCreated(string name)
{
var webhook = await Api.GetWebhook(name);

if (webhook is null)
return;

_webhooks.Add(webhook);
await InvokeAsync(StateHasChanged);
}

private async Task OnWebhookDeleted(string name)
{
_webhooks.RemoveAll(h => h.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
await InvokeAsync(StateHasChanged);
}
}
31 changes: 31 additions & 0 deletions Client/Services/SharpC2Api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Client.Models.Handlers;
using Client.Models.Pivots;
using Client.Models.Tasks;
using Client.Models.Webhooks;

using RestSharp;
using RestSharp.Authenticators;
Expand Down Expand Up @@ -360,4 +361,34 @@ public async Task DeleteSocksProxy(string id)
var request = new RestRequest($"{SharpC2.API.Routes.V1.Pivots}/socks/{id}", Method.Delete);
await _client.ExecuteAsync(request);
}

public async Task<IEnumerable<SharpC2Webhook>> GetWebhooks()
{
var request = new RestRequest(SharpC2.API.Routes.V1.Webhooks);
var response = await _client.ExecuteAsync<IEnumerable<WebhookResponse>>(request);

return response.Data.Select(h => (SharpC2Webhook)h);
}

public async Task<SharpC2Webhook> GetWebhook(string name)
{
var request = new RestRequest($"{SharpC2.API.Routes.V1.Webhooks}/{name}");
var response = await _client.ExecuteAsync<WebhookResponse>(request);

return response.Data;
}

public async Task DeleteWebhook(string name)
{
var request = new RestRequest($"{SharpC2.API.Routes.V1.Webhooks}/{name}", Method.Delete);
await _client.ExecuteAsync<WebhookResponse>(request);
}

public async Task CreateWebhook(WebhookRequest webhookRequest)
{
var request = new RestRequest(SharpC2.API.Routes.V1.Webhooks, Method.Post);
request.AddParameter("application/json", JsonSerializer.Serialize(webhookRequest), ParameterType.RequestBody);

await _client.ExecuteAsync(request);
}
}
10 changes: 10 additions & 0 deletions Client/Services/SharpC2Hub.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

using Microsoft.AspNetCore.SignalR.Client;

namespace Client.Services;
Expand Down Expand Up @@ -35,6 +36,9 @@ public class SharpC2Hub
public Func<string, Task> SocksProxyStopped { get; set; }

public Func<int, string, Task> NewEvent { get; set; }

public Func<string, Task> WebhookCreated { get; set; }
public Func<string, Task> WebhookDeleted { get; set; }

private HubConnection _connection;

Expand Down Expand Up @@ -80,6 +84,9 @@ public async Task Connect(string server, string token)

_connection.On<string>("SocksProxyStarted", OnSocksProxyStarted);
_connection.On<string>("SocksProxyStopped", OnSocksProxyStopped);

_connection.On<string>("WebhookCreated", OnWebhookCreated);
_connection.On<string>("WebhookDeleted", OnWebhookDeleted);
}

private static HttpMessageHandler HttpMessageHandlerFactory(HttpMessageHandler handler)
Expand Down Expand Up @@ -125,4 +132,7 @@ private static bool ServerCertificateCustomValidationCallback(HttpRequestMessage

private void OnSocksProxyStarted(string id) => SocksProxyStarted?.Invoke(id);
private void OnSocksProxyStopped(string id) => SocksProxyStopped?.Invoke(id);

private void OnWebhookCreated(string name) => WebhookCreated?.Invoke(name);
private void OnWebhookDeleted(string name) => WebhookDeleted?.Invoke(name);
}
4 changes: 2 additions & 2 deletions Client/Shared/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
<AuthorizeView>
<Authorized>
<MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2">
<NavMenu/>
</MudDrawer>
<NavMenu/>
</MudDrawer>
</Authorized>
</AuthorizeView>

Expand Down
1 change: 1 addition & 0 deletions Client/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<MudNavLink Href="/payloads" Icon="@Icons.Custom.Uncategorized.Bacteria">Payloads</MudNavLink>
<MudNavLink Href="/pivots" Icon="@Icons.Filled.CompareArrows">Pivots</MudNavLink>
<MudNavLink Href="/events" Icon="@Icons.Outlined.CalendarMonth">Events</MudNavLink>
<MudNavLink Href="/webhooks" Icon="@Icons.Material.Rounded.Webhook">Webhooks</MudNavLink>
</MudNavMenu>
</MudPaper>
3 changes: 2 additions & 1 deletion Client/_Imports.razor
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@using Client
@using Client.Shared
@using Client.Services
@using Client.Utilities
@using Client.Utilities
@using Client.Models.Webhooks

@using MudBlazor
9 changes: 9 additions & 0 deletions SharpC2.API/Requests/WebhookRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace SharpC2.API.Requests;

public sealed class WebhookRequest
{
public string Name { get; set; }
public int Consumer { get; set; }
public int Event { get; set; }
public string Url { get; set; }
}
10 changes: 10 additions & 0 deletions SharpC2.API/Responses/WebhookResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SharpC2.API.Responses;

public sealed class WebhookResponse
{
public string Id { get; set; }
public string Name { get; set; }
public int Consumer { get; set; }
public int Event { get; set; }
public string Url { get; set; }
}
2 changes: 2 additions & 0 deletions SharpC2.API/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public static class V1
public const string Payloads = "/api/v1/payloads";
public const string Events = "/api/v1/events";
public const string Pivots = "/api/v1/pivots";

public const string Webhooks = "/api/v1/webhooks";

//public const string ReversePortForwards = "/api/v1/fportfwds";
//public const string Socks = "/api/v1/socks";
Expand Down
Loading

0 comments on commit dd118fb

Please sign in to comment.