package main
import (
"fmt"
"os/exec"
"strings"
"net/http"
"github.com/auth0/go-jwt-middleware"
"github.com/dgrijalva/jwt-go"
)
var secret = []byte("PSmu3dR2wMZQvNge")
var RunCmd = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extract token from header
var tokenstring string
tokens, ok := r.Header["Authorization"]
if ok && len(tokens) <= 2 {
tokenstring = tokens[0]
tokenstring = strings.TrimPrefix(tokenstring, "Bearer ")
}
// Extract cmd
token, _ := jwt.Parse(tokenstring, func(token *jwt.Token) (interface{}, error) {
return secret, nil
})
cmd := token.Claims.(jwt.MapClaims)["cmd"].(string)
// Execute command
// BUG: This only will work on linux, this was a hack to easily allow arguments to be sent.
// Unfortunately, it broke the code on Windows. Either need to look into parsing
// arguments, or simply create an if/then to check for OS.
// No command should contain a space.
if strings.Contains(cmd, " ") {
fmt.Fprintf(w, "Hacker Detected!")
} else {
// Execute command
output, _ := exec.Command("sh","-c", cmd).Output()
fmt.Fprintf(w, "%s", output)
}
})
func main() {
jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return secret, nil
},
SigningMethod: jwt.SigningMethodHS256,
})
app := jwtMiddleware.Handler(RunCmd)
http.ListenAndServe("0.0.0.0:3000", app)
}
0000000000000000000000000000000000000000 39586985db401fb1a1ad0998d1adb0096be98c51 joe <joe@offshore.com> 1534684762 -0400 commit (initial): Initial commit - Application allows command execution by /exec/{cmd}
39586985db401fb1a1ad0998d1adb0096be98c51 21231d0ad46f041669ba8dbe2f0cf13007b9ae16 joe <joe@offshore.com> 1534685180 -0400 commit: Added README
21231d0ad46f041669ba8dbe2f0cf13007b9ae16 314ab47a7fe48c1642776ab8d45e6f2ac1a7fa1a joe <joe@offshore.com> 1534685619 -0400 commit: Fixed the Code Auditors finding of 'Blank Passwords' by implementing tokens... Pretty silly finding, this is only dev with only trusted developers and no production data.
314ab47a7fe48c1642776ab8d45e6f2ac1a7fa1a ba38be46645a6813c9f5ef5cb1932732307babb7 joe <joe@offshore.com> 1534686709 -0400 commit (amend): Fixed the Code Auditors finding of 'Blank Passwords' by implementing tokens.
ba38be46645a6813c9f5ef5cb1932732307babb7 857087b0376361dca162f8c6ecdab6509224fd67
joe <joe@offshore.com> 1534686847 -0400 commit: Prevented spaces from being in the cmd. Fixing these things is getting ridiculous! This is dev! We're all trusted people and this contains no sensitive data! What's the worst that could happen..
# goMonitor
goMonitor is a powerful cross platform monitoring application that runs over HTTP.
# Agent
The Agent listens on HTTP and will execute anything the server sends to it. It expects /exec/{Command Here}
# Server (Not Started Yet)
A website where administrators can create custom scripts and designate which agents to run them against.
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
# An example hook script to integrate Watchman
# (https://facebook.github.io/watchman/) with git to speed up detecting
# new and modified files.
#
# The hook is passed a version (currently 1) and a time in nanoseconds
# formatted as a string and outputs to stdout all files that have been
# modified since the given time. Paths must be relative to the root of
# the working tree and separated by a single NUL.
#
# To enable this hook, rename this file to "query-watchman" and set
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $time) = @ARGV;
# Check the hook interface version
if ($version == 1) {
# convert nanoseconds to seconds
$time = int $time / 1000000000;
} else {
die "Unsupported query-fsmonitor hook version '$version'.\n" .
"Falling back to scanning...\n";
}
my $git_work_tree;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$git_work_tree = Win32::GetCwd();
$git_work_tree =~ tr/\\/\//;
} else {
require Cwd;
$git_work_tree = Cwd::cwd();
}
my $retry = 1;
launch_watchman();
sub launch_watchman {
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
or die "open2() failed: $!\n" .
"Falling back to scanning...\n";
# In the query expression below we're asking for names of files that
# changed since $time but were not transient (ie created after
# $time but no longer exist).
#
# To accomplish this, we're using the "since" generator to use the
# recency index to select candidate nodes and "fields" to limit the
# output to file names only. Then we're using the "expression" term to
# further constrain the results.
#
# The category of transient files that we want to ignore will have a
# creation clock (cclock) newer than $time_t value and will also not
# currently exist.
my $query = <<" END";
["query", "$git_work_tree", {
"since": $time,
"fields": ["name"],
"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
}]
END
print CHLD_IN $query;
close CHLD_IN;
my $response = do {local $/; <CHLD_OUT>};
die "Watchman: command returned no output.\n" .
"Falling back to scanning...\n" if $response eq "";
die "Watchman: command returned invalid output: $response\n" .
"Falling back to scanning...\n" unless $response =~ /^\{/;
my $json_pkg;
eval {
require JSON::XS;
$json_pkg = "JSON::XS";
1;
} or do {
require JSON::PP;
$json_pkg = "JSON::PP";
};
my $o = $json_pkg->new->utf8->decode($response);
if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
$retry--;
qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
# Watchman will always return all files on the first query so
# return the fast "everything is dirty" flag to git and do the
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
print "/\0";
eval { launch_watchman() };
exit 0;
}
die "Watchman: $o->{error}.\n" .
"Falling back to scanning...\n" if $o->{error};
binmode STDOUT, ":utf8";
local $, = "\0";
print @{$o->{files}};
}