mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-08 18:22:47 +01:00
Merge branch 'dev' of https://github.com/Security-Onion-Solutions/securityonion into dev
This commit is contained in:
@@ -140,3 +140,32 @@ get_random_value() {
|
|||||||
length=${1:-20}
|
length=${1:-20}
|
||||||
head -c 5000 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1
|
head -c 5000 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait_for_web_response() {
|
||||||
|
url=$1
|
||||||
|
expected=$2
|
||||||
|
maxAttempts=${3:-300}
|
||||||
|
logfile=/root/wait_for_web_response.log
|
||||||
|
attempt=0
|
||||||
|
while [[ $attempt -lt $maxAttempts ]]; do
|
||||||
|
attempt=$((attempt+1))
|
||||||
|
echo "Waiting for value '$expected' at '$url' ($attempt/$maxAttempts)"
|
||||||
|
result=$(curl -ks -L $url)
|
||||||
|
exitcode=$?
|
||||||
|
|
||||||
|
echo "--------------------------------------------------" >> $logfile
|
||||||
|
echo "$(date) - Checking web URL: $url ($attempt/$maxAttempts)" >> $logfile
|
||||||
|
echo "$result" >> $logfile
|
||||||
|
echo "exit code=$exitcode" >> $logfile
|
||||||
|
echo "" >> $logfile
|
||||||
|
|
||||||
|
if [[ $exitcode -eq 0 && "$result" =~ $expected ]]; then
|
||||||
|
echo "Received expected response; proceeding."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "Server is not ready"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "Server still not ready after $maxAttempts attempts; giving up."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
@@ -96,7 +96,7 @@ rule_prompt(){
|
|||||||
echo "-----------------------------------"
|
echo "-----------------------------------"
|
||||||
echo
|
echo
|
||||||
while [ -z "$RULE_NAME" ]; do
|
while [ -z "$RULE_NAME" ]; do
|
||||||
read -p "Please enter the rule filename you want to test (filename only, no path): " -e RULE_NAME
|
read -p "Choose a rule to test from the list above (must be typed exactly as shown above): " -e RULE_NAME
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,25 +21,33 @@ import yaml
|
|||||||
|
|
||||||
hostgroupsFilename = "/opt/so/saltstack/local/salt/firewall/hostgroups.local.yaml"
|
hostgroupsFilename = "/opt/so/saltstack/local/salt/firewall/hostgroups.local.yaml"
|
||||||
portgroupsFilename = "/opt/so/saltstack/local/salt/firewall/portgroups.local.yaml"
|
portgroupsFilename = "/opt/so/saltstack/local/salt/firewall/portgroups.local.yaml"
|
||||||
|
defaultPortgroupsFilename = "/opt/so/saltstack/default/salt/firewall/portgroups.yaml"
|
||||||
supportedProtocols = ['tcp', 'udp']
|
supportedProtocols = ['tcp', 'udp']
|
||||||
|
|
||||||
def showUsage(args):
|
def showUsage(options, args):
|
||||||
print('Usage: {} [OPTIONS] <COMMAND> [ARGS...]'.format(sys.argv[0]))
|
print('Usage: {} [OPTIONS] <COMMAND> [ARGS...]'.format(sys.argv[0]))
|
||||||
print(' Options:')
|
print(' Options:')
|
||||||
print(' --apply - After updating the firewall configuration files, apply the new firewall state')
|
print(' --apply - After updating the firewall configuration files, apply the new firewall state')
|
||||||
|
print(' --defaultports - Read port groups from default configuration files instead of local configuration.')
|
||||||
print('')
|
print('')
|
||||||
print(' Available commands:')
|
print(' General commands:')
|
||||||
print(' help - Prints this usage information.')
|
print(' help - Prints this usage information.')
|
||||||
print(' includedhosts - Lists the IPs included in the given group. Args: <GROUP_NAME>')
|
print('')
|
||||||
print(' excludedhosts - Lists the IPs excluded from the given group. Args: <GROUP_NAME>')
|
print(' Host commands:')
|
||||||
print(' includehost - Includes the given IP in the given group. Args: <GROUP_NAME> <IP>')
|
print(' listhostgroups - Lists the known host groups.')
|
||||||
print(' excludehost - Excludes the given IP from the given group. Args: <GROUP_NAME> <IP>')
|
print(' includedhosts - Lists the IPs included in the given group. Args: <GROUP_NAME>')
|
||||||
print(' removehost - Removes an excluded IP from the given group. Args: <GROUP_NAME> <IP>')
|
print(' excludedhosts - Lists the IPs excluded from the given group. Args: <GROUP_NAME>')
|
||||||
print(' addhostgroup - Adds a new, custom host group. Args: <GROUP_NAME>')
|
print(' includehost - Includes the given IP in the given group. Args: <GROUP_NAME> <IP>')
|
||||||
print(' listports - Lists ports in the given group and protocol. Args: <GROUP_NAME> <PORT_PROTOCOL>')
|
print(' excludehost - Excludes the given IP from the given group. Args: <GROUP_NAME> <IP>')
|
||||||
print(' addport - Adds a PORT to the given group. Args: <GROUP_NAME> <PORT_PROTOCOL> <PORT>')
|
print(' removehost - Removes an excluded IP from the given group. Args: <GROUP_NAME> <IP>')
|
||||||
print(' removeport - Removes a PORT from the given group. Args: <GROUP_NAME> <PORT_PROTOCOL> <PORT>')
|
print(' addhostgroup - Adds a new, custom host group. Args: <GROUP_NAME>')
|
||||||
print(' addportgroup - Adds a new, custom port group. Args: <GROUP_NAME>')
|
print('')
|
||||||
|
print(' Port commands:')
|
||||||
|
print(' listportgroups - Lists the known port groups.')
|
||||||
|
print(' listports - Lists ports in the given group and protocol. Args: <GROUP_NAME> <PORT_PROTOCOL>')
|
||||||
|
print(' addport - Adds a PORT to the given group. Args: <GROUP_NAME> <PORT_PROTOCOL> <PORT>')
|
||||||
|
print(' removeport - Removes a PORT from the given group. Args: <GROUP_NAME> <PORT_PROTOCOL> <PORT>')
|
||||||
|
print(' addportgroup - Adds a new, custom port group. Args: <GROUP_NAME>')
|
||||||
print('')
|
print('')
|
||||||
print(' Where:')
|
print(' Where:')
|
||||||
print(' GROUP_NAME - The name of an alias group (Ex: analyst)')
|
print(' GROUP_NAME - The name of an alias group (Ex: analyst)')
|
||||||
@@ -48,6 +56,15 @@ def showUsage(args):
|
|||||||
print(' PORT - Either a single numeric port (Ex: 443), or a port range (Ex: 8000:8002).')
|
print(' PORT - Either a single numeric port (Ex: 443), or a port range (Ex: 8000:8002).')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def checkDefaultPortsOption(options):
|
||||||
|
global portgroupsFilename
|
||||||
|
if "--defaultports" in options:
|
||||||
|
portgroupsFilename = defaultPortgroupsFilename
|
||||||
|
|
||||||
|
def checkApplyOption(options):
|
||||||
|
if "--apply" in options:
|
||||||
|
return apply()
|
||||||
|
|
||||||
def loadYaml(filename):
|
def loadYaml(filename):
|
||||||
file = open(filename, "r")
|
file = open(filename, "r")
|
||||||
return yaml.load(file.read())
|
return yaml.load(file.read())
|
||||||
@@ -56,6 +73,14 @@ def writeYaml(filename, content):
|
|||||||
file = open(filename, "w")
|
file = open(filename, "w")
|
||||||
return yaml.dump(content, file)
|
return yaml.dump(content, file)
|
||||||
|
|
||||||
|
def listHostGroups():
|
||||||
|
content = loadYaml(hostgroupsFilename)
|
||||||
|
hostgroups = content['firewall']['hostgroups']
|
||||||
|
if hostgroups is not None:
|
||||||
|
for group in hostgroups:
|
||||||
|
print(group)
|
||||||
|
return 0
|
||||||
|
|
||||||
def listIps(name, mode):
|
def listIps(name, mode):
|
||||||
content = loadYaml(hostgroupsFilename)
|
content = loadYaml(hostgroupsFilename)
|
||||||
if name not in content['firewall']['hostgroups']:
|
if name not in content['firewall']['hostgroups']:
|
||||||
@@ -111,10 +136,18 @@ def createProtocolMap():
|
|||||||
map[protocol] = []
|
map[protocol] = []
|
||||||
return map
|
return map
|
||||||
|
|
||||||
def addhostgroup(args):
|
def listPortGroups():
|
||||||
|
content = loadYaml(portgroupsFilename)
|
||||||
|
portgroups = content['firewall']['aliases']['ports']
|
||||||
|
if portgroups is not None:
|
||||||
|
for group in portgroups:
|
||||||
|
print(group)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def addhostgroup(options, args):
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
print('Missing host group name argument', file=sys.stderr)
|
print('Missing host group name argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
|
|
||||||
name = args[0]
|
name = args[0]
|
||||||
content = loadYaml(hostgroupsFilename)
|
content = loadYaml(hostgroupsFilename)
|
||||||
@@ -125,10 +158,17 @@ def addhostgroup(args):
|
|||||||
writeYaml(hostgroupsFilename, content)
|
writeYaml(hostgroupsFilename, content)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def addportgroup(args):
|
def listportgroups(options, args):
|
||||||
|
if len(args) != 0:
|
||||||
|
print('Unexpected arguments', file=sys.stderr)
|
||||||
|
showUsage(options, args)
|
||||||
|
checkDefaultPortsOption(options)
|
||||||
|
return listPortGroups()
|
||||||
|
|
||||||
|
def addportgroup(options, args):
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
print('Missing port group name argument', file=sys.stderr)
|
print('Missing port group name argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
|
|
||||||
name = args[0]
|
name = args[0]
|
||||||
content = loadYaml(portgroupsFilename)
|
content = loadYaml(portgroupsFilename)
|
||||||
@@ -143,11 +183,12 @@ def addportgroup(args):
|
|||||||
writeYaml(portgroupsFilename, content)
|
writeYaml(portgroupsFilename, content)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def listports(args):
|
def listports(options, args):
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
print('Missing port group name or port protocol', file=sys.stderr)
|
print('Missing port group name or port protocol', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
|
|
||||||
|
checkDefaultPortsOption(options)
|
||||||
name = args[0]
|
name = args[0]
|
||||||
protocol = args[1]
|
protocol = args[1]
|
||||||
if protocol not in supportedProtocols:
|
if protocol not in supportedProtocols:
|
||||||
@@ -162,16 +203,19 @@ def listports(args):
|
|||||||
if name not in ports:
|
if name not in ports:
|
||||||
print('Port group does not exist', file=sys.stderr)
|
print('Port group does not exist', file=sys.stderr)
|
||||||
return 3
|
return 3
|
||||||
|
if protocol not in ports[name]:
|
||||||
|
print('Port group does not contain protocol', file=sys.stderr)
|
||||||
|
return 3
|
||||||
ports = ports[name][protocol]
|
ports = ports[name][protocol]
|
||||||
if ports is not None:
|
if ports is not None:
|
||||||
for port in ports:
|
for port in ports:
|
||||||
print(port)
|
print(port)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def addport(args):
|
def addport(options, args):
|
||||||
if len(args) != 3:
|
if len(args) != 3:
|
||||||
print('Missing port group name or port protocol, or port argument', file=sys.stderr)
|
print('Missing port group name or port protocol, or port argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
|
|
||||||
name = args[0]
|
name = args[0]
|
||||||
protocol = args[1]
|
protocol = args[1]
|
||||||
@@ -197,12 +241,13 @@ def addport(args):
|
|||||||
return 3
|
return 3
|
||||||
ports.append(port)
|
ports.append(port)
|
||||||
writeYaml(portgroupsFilename, content)
|
writeYaml(portgroupsFilename, content)
|
||||||
return 0
|
code = checkApplyOption(options)
|
||||||
|
return code
|
||||||
|
|
||||||
def removeport(args):
|
def removeport(options, args):
|
||||||
if len(args) != 3:
|
if len(args) != 3:
|
||||||
print('Missing port group name or port protocol, or port argument', file=sys.stderr)
|
print('Missing port group name or port protocol, or port argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
|
|
||||||
name = args[0]
|
name = args[0]
|
||||||
protocol = args[1]
|
protocol = args[1]
|
||||||
@@ -225,43 +270,60 @@ def removeport(args):
|
|||||||
return 3
|
return 3
|
||||||
ports.remove(port)
|
ports.remove(port)
|
||||||
writeYaml(portgroupsFilename, content)
|
writeYaml(portgroupsFilename, content)
|
||||||
return 0
|
code = checkApplyOption(options)
|
||||||
|
return code
|
||||||
|
|
||||||
def includedhosts(args):
|
|
||||||
|
def listhostgroups(options, args):
|
||||||
|
if len(args) != 0:
|
||||||
|
print('Unexpected arguments', file=sys.stderr)
|
||||||
|
showUsage(options, args)
|
||||||
|
return listHostGroups()
|
||||||
|
|
||||||
|
def includedhosts(options, args):
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
print('Missing host group name argument', file=sys.stderr)
|
print('Missing host group name argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
return listIps(args[0], 'insert')
|
return listIps(args[0], 'insert')
|
||||||
|
|
||||||
def excludedhosts(args):
|
def excludedhosts(options, args):
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
print('Missing host group name argument', file=sys.stderr)
|
print('Missing host group name argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
return listIps(args[0], 'delete')
|
return listIps(args[0], 'delete')
|
||||||
|
|
||||||
def includehost(args):
|
def includehost(options, args):
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
print('Missing host group name or ip argument', file=sys.stderr)
|
print('Missing host group name or ip argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
result = addIp(args[0], args[1], 'insert')
|
result = addIp(args[0], args[1], 'insert')
|
||||||
if result == 0:
|
if result == 0:
|
||||||
removeIp(args[0], args[1], 'delete', True)
|
removeIp(args[0], args[1], 'delete', True)
|
||||||
return result
|
code = result
|
||||||
|
if code == 0:
|
||||||
|
code = checkApplyOption(options)
|
||||||
|
return code
|
||||||
|
|
||||||
def excludehost(args):
|
def excludehost(options, args):
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
print('Missing host group name or ip argument', file=sys.stderr)
|
print('Missing host group name or ip argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
result = addIp(args[0], args[1], 'delete')
|
result = addIp(args[0], args[1], 'delete')
|
||||||
if result == 0:
|
if result == 0:
|
||||||
removeIp(args[0], args[1], 'insert', True)
|
removeIp(args[0], args[1], 'insert', True)
|
||||||
return result
|
code = result
|
||||||
|
if code == 0:
|
||||||
|
code = checkApplyOption(options)
|
||||||
|
return code
|
||||||
|
|
||||||
def removehost(args):
|
def removehost(options, args):
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
print('Missing host group name or ip argument', file=sys.stderr)
|
print('Missing host group name or ip argument', file=sys.stderr)
|
||||||
showUsage(args)
|
showUsage(options, args)
|
||||||
return removeIp(args[0], args[1], 'delete')
|
code = removeIp(args[0], args[1], 'delete')
|
||||||
|
if code == 0:
|
||||||
|
code = checkApplyOption(options)
|
||||||
|
return code
|
||||||
|
|
||||||
def apply():
|
def apply():
|
||||||
proc = subprocess.run(['salt-call', 'state.apply', 'firewall', 'queue=True'])
|
proc = subprocess.run(['salt-call', 'state.apply', 'firewall', 'queue=True'])
|
||||||
@@ -276,15 +338,17 @@ def main():
|
|||||||
args.remove(option)
|
args.remove(option)
|
||||||
|
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
showUsage(None)
|
showUsage(options, None)
|
||||||
|
|
||||||
commands = {
|
commands = {
|
||||||
"help": showUsage,
|
"help": showUsage,
|
||||||
|
"listhostgroups": listhostgroups,
|
||||||
"includedhosts": includedhosts,
|
"includedhosts": includedhosts,
|
||||||
"excludedhosts": excludedhosts,
|
"excludedhosts": excludedhosts,
|
||||||
"includehost": includehost,
|
"includehost": includehost,
|
||||||
"excludehost": excludehost,
|
"excludehost": excludehost,
|
||||||
"removehost": removehost,
|
"removehost": removehost,
|
||||||
|
"listportgroups": listportgroups,
|
||||||
"listports": listports,
|
"listports": listports,
|
||||||
"addport": addport,
|
"addport": addport,
|
||||||
"removeport": removeport,
|
"removeport": removeport,
|
||||||
@@ -293,11 +357,7 @@ def main():
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd = commands.get(args[0], showUsage)
|
cmd = commands.get(args[0], showUsage)
|
||||||
code = cmd(args[1:])
|
code = cmd(options, args[1:])
|
||||||
|
|
||||||
|
|
||||||
if code == 0 and "--apply" in options:
|
|
||||||
code = apply()
|
|
||||||
|
|
||||||
sys.exit(code)
|
sys.exit(code)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ echo "Starting to check for yara rule updates at $(date)..."
|
|||||||
|
|
||||||
output_dir="/opt/so/saltstack/default/salt/strelka/rules"
|
output_dir="/opt/so/saltstack/default/salt/strelka/rules"
|
||||||
mkdir -p $output_dir
|
mkdir -p $output_dir
|
||||||
|
|
||||||
repos="$output_dir/repos.txt"
|
repos="$output_dir/repos.txt"
|
||||||
ignorefile="$output_dir/ignore.txt"
|
ignorefile="$output_dir/ignore.txt"
|
||||||
|
|
||||||
@@ -95,55 +96,56 @@ clone_dir="/tmp"
|
|||||||
if [ "$gh_status" == "200" ] || [ "$gh_status" == "301" ]; then
|
if [ "$gh_status" == "200" ] || [ "$gh_status" == "301" ]; then
|
||||||
|
|
||||||
while IFS= read -r repo; do
|
while IFS= read -r repo; do
|
||||||
|
if ! $(echo "$repo" | grep -qE '^#'); then
|
||||||
|
# Remove old repo if existing bc of previous error condition or unexpected disruption
|
||||||
|
repo_name=`echo $repo | awk -F '/' '{print $NF}'`
|
||||||
|
[ -d $repo_name ] && rm -rf $repo_name
|
||||||
|
|
||||||
# Remove old repo if existing bc of previous error condition or unexpected disruption
|
# Clone repo and make appropriate directories for rules
|
||||||
repo_name=`echo $repo | awk -F '/' '{print $NF}'`
|
|
||||||
[ -d $repo_name ] && rm -rf $repo_name
|
|
||||||
|
|
||||||
# Clone repo and make appropriate directories for rules
|
git clone $repo $clone_dir/$repo_name
|
||||||
|
echo "Analyzing rules from $clone_dir/$repo_name..."
|
||||||
|
mkdir -p $output_dir/$repo_name
|
||||||
|
[ -f $clone_dir/$repo_name/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
|
||||||
|
|
||||||
git clone $repo $clone_dir/$repo_name
|
# Copy over rules
|
||||||
echo "Analyzing rules from $clone_dir/$repo_name..."
|
for i in $(find $clone_dir/$repo_name -name "*.yar*"); do
|
||||||
mkdir -p $output_dir/$repo_name
|
rule_name=$(echo $i | awk -F '/' '{print $NF}')
|
||||||
[ -f $clone_dir/$repo_name/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
|
repo_sum=$(sha256sum $i | awk '{print $1}')
|
||||||
|
|
||||||
# Copy over rules
|
# Check rules against those in ignore list -- don't copy if ignored.
|
||||||
for i in $(find $clone_dir/$repo_name -name "*.yar*"); do
|
if ! grep -iq $rule_name $ignorefile; then
|
||||||
rule_name=$(echo $i | awk -F '/' '{print $NF}')
|
existing_rules=$(find $output_dir/$repo_name/ -name $rule_name | wc -l)
|
||||||
repo_sum=$(sha256sum $i | awk '{print $1}')
|
|
||||||
|
|
||||||
# Check rules against those in ignore list -- don't copy if ignored.
|
# For existing rules, check to see if they need to be updated, by comparing checksums
|
||||||
if ! grep -iq $rule_name $ignorefile; then
|
if [ $existing_rules -gt 0 ];then
|
||||||
existing_rules=$(find $output_dir/$repo_name/ -name $rule_name | wc -l)
|
local_sum=$(sha256sum $output_dir/$repo_name/$rule_name | awk '{print $1}')
|
||||||
|
if [ "$repo_sum" != "$local_sum" ]; then
|
||||||
# For existing rules, check to see if they need to be updated, by comparing checksums
|
echo "Checksums do not match!"
|
||||||
if [ $existing_rules -gt 0 ];then
|
echo "Updating $rule_name..."
|
||||||
local_sum=$(sha256sum $output_dir/$repo_name/$rule_name | awk '{print $1}')
|
cp $i $output_dir/$repo_name;
|
||||||
if [ "$repo_sum" != "$local_sum" ]; then
|
((updatecounter++))
|
||||||
echo "Checksums do not match!"
|
fi
|
||||||
echo "Updating $rule_name..."
|
else
|
||||||
cp $i $output_dir/$repo_name;
|
# If rule doesn't exist already, we'll add it
|
||||||
((updatecounter++))
|
echo "Adding new rule: $rule_name..."
|
||||||
|
cp $i $output_dir/$repo_name
|
||||||
|
((newcounter++))
|
||||||
fi
|
fi
|
||||||
else
|
fi;
|
||||||
# If rule doesn't exist already, we'll add it
|
done
|
||||||
echo "Adding new rule: $rule_name..."
|
|
||||||
cp $i $output_dir/$repo_name
|
|
||||||
((newcounter++))
|
|
||||||
fi
|
|
||||||
fi;
|
|
||||||
done
|
|
||||||
|
|
||||||
# Check to see if we have any old rules that need to be removed
|
# Check to see if we have any old rules that need to be removed
|
||||||
for i in $(find $output_dir/$repo_name -name "*.yar*" | awk -F '/' '{print $NF}'); do
|
for i in $(find $output_dir/$repo_name -name "*.yar*" | awk -F '/' '{print $NF}'); do
|
||||||
is_repo_rule=$(find $clone_dir/$repo_name -name "$i" | wc -l)
|
is_repo_rule=$(find $clone_dir/$repo_name -name "$i" | wc -l)
|
||||||
if [ $is_repo_rule -eq 0 ]; then
|
if [ $is_repo_rule -eq 0 ]; then
|
||||||
echo "Could not find $i in source $repo_name repo...removing from $output_dir/$repo_name..."
|
echo "Could not find $i in source $repo_name repo...removing from $output_dir/$repo_name..."
|
||||||
rm $output_dir/$repo_name/$i
|
rm $output_dir/$repo_name/$i
|
||||||
((deletecounter++))
|
((deletecounter++))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
rm -rf $clone_dir/$repo_name
|
rm -rf $clone_dir/$repo_name
|
||||||
|
fi
|
||||||
done < $repos
|
done < $repos
|
||||||
|
|
||||||
echo "Done!"
|
echo "Done!"
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ strelkarules:
|
|||||||
- user: 939
|
- user: 939
|
||||||
- group: 939
|
- group: 939
|
||||||
|
|
||||||
|
strelkarepos:
|
||||||
|
file.managed:
|
||||||
|
- name: /opt/so/saltstack/default/salt/strelka/rules/repos.txt
|
||||||
|
- source: salt://strelka/rules/repos.txt.jinja
|
||||||
|
- template: jinja
|
||||||
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
strelkadatadir:
|
strelkadatadir:
|
||||||
|
|||||||
4
salt/strelka/rules/repos.txt.jinja
Normal file
4
salt/strelka/rules/repos.txt.jinja
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# DO NOT EDIT THIS FILE! Strelka YARA rule repos are stored here from the strelka.repos pillar section
|
||||||
|
{%- for repo in salt['pillar.get']('strelka:repos', {}) %}
|
||||||
|
{{ repo }}
|
||||||
|
{%- endfor %}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# {%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
|
||||||
# {%- set URLBASE = salt['pillar.get']('global:url_base', '') %}
|
# {%- set URLBASE = salt['pillar.get']('global:url_base', '') %}
|
||||||
# {%- set CORTEXUSER = salt['pillar.get']('global:cortexuser', 'cortexadmin') %}
|
# {%- set CORTEXUSER = salt['pillar.get']('global:cortexuser', 'cortexadmin') %}
|
||||||
# {%- set CORTEXPASSWORD = salt['pillar.get']('global:cortexpassword', 'cortexchangeme') %}
|
# {%- set CORTEXPASSWORD = salt['pillar.get']('global:cortexpassword', 'cortexchangeme') %}
|
||||||
@@ -7,6 +8,8 @@
|
|||||||
# {%- set CORTEXORGUSER = salt['pillar.get']('global:cortexorguser', 'soadmin') %}
|
# {%- set CORTEXORGUSER = salt['pillar.get']('global:cortexorguser', 'soadmin') %}
|
||||||
# {%- set CORTEXORGUSERKEY = salt['pillar.get']('global:cortexorguserkey', '') %}
|
# {%- set CORTEXORGUSERKEY = salt['pillar.get']('global:cortexorguserkey', '') %}
|
||||||
|
|
||||||
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
default_salt_dir=/opt/so/saltstack/default
|
default_salt_dir=/opt/so/saltstack/default
|
||||||
|
|
||||||
cortex_clean(){
|
cortex_clean(){
|
||||||
@@ -16,8 +19,8 @@ cortex_clean(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
cortex_init(){
|
cortex_init(){
|
||||||
sleep 60
|
CORTEX_URL="{{URLBASE}}/cortex"
|
||||||
CORTEX_API_URL="{{URLBASE}}/cortex/api"
|
CORTEX_API_URL="{{CORTEX_URL}}/api"
|
||||||
CORTEX_USER="{{CORTEXUSER}}"
|
CORTEX_USER="{{CORTEXUSER}}"
|
||||||
CORTEX_PASSWORD="{{CORTEXPASSWORD}}"
|
CORTEX_PASSWORD="{{CORTEXPASSWORD}}"
|
||||||
CORTEX_KEY="{{CORTEXKEY}}"
|
CORTEX_KEY="{{CORTEXKEY}}"
|
||||||
@@ -27,47 +30,45 @@ cortex_init(){
|
|||||||
CORTEX_ORG_USER_KEY="{{CORTEXORGUSERKEY}}"
|
CORTEX_ORG_USER_KEY="{{CORTEXORGUSERKEY}}"
|
||||||
SOCTOPUS_CONFIG="$default_salt_dir/salt/soctopus/files/SOCtopus.conf"
|
SOCTOPUS_CONFIG="$default_salt_dir/salt/soctopus/files/SOCtopus.conf"
|
||||||
|
|
||||||
|
if wait_for_web_response https://$CORTEX_URL "Cortex"; then
|
||||||
|
# Migrate DB
|
||||||
|
curl -v -k -XPOST -L "https://$CORTEX_API_URL/maintenance/migrate"
|
||||||
|
|
||||||
# Migrate DB
|
# Create intial Cortex superadmin
|
||||||
curl -v -k -XPOST -L "https://$CORTEX_API_URL/maintenance/migrate"
|
curl -v -k -L "https://$CORTEX_API_URL/user" -H "Content-Type: application/json" -d "{\"login\" : \"$CORTEX_USER\",\"name\" : \"$CORTEX_USER\",\"roles\" : [\"superadmin\"],\"preferences\" : \"{}\",\"password\" : \"$CORTEX_PASSWORD\", \"key\": \"$CORTEX_KEY\"}"
|
||||||
|
|
||||||
# Create intial Cortex superadmin
|
# Create user-supplied org
|
||||||
curl -v -k -L "https://$CORTEX_API_URL/user" -H "Content-Type: application/json" -d "{\"login\" : \"$CORTEX_USER\",\"name\" : \"$CORTEX_USER\",\"roles\" : [\"superadmin\"],\"preferences\" : \"{}\",\"password\" : \"$CORTEX_PASSWORD\", \"key\": \"$CORTEX_KEY\"}"
|
curl -k -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization" -d "{ \"name\": \"$CORTEX_ORG_NAME\",\"description\": \"$CORTEX_ORG_DESC\",\"status\": \"Active\"}"
|
||||||
|
|
||||||
# Create user-supplied org
|
# Create user-supplied org user
|
||||||
curl -k -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization" -d "{ \"name\": \"$CORTEX_ORG_NAME\",\"description\": \"$CORTEX_ORG_DESC\",\"status\": \"Active\"}"
|
curl -k -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/user" -d "{\"name\": \"$CORTEX_ORG_USER\",\"roles\": [\"read\",\"analyze\",\"orgadmin\"],\"organization\": \"$CORTEX_ORG_NAME\",\"login\": \"$CORTEX_ORG_USER\",\"key\": \"$CORTEX_ORG_USER_KEY\" }"
|
||||||
|
|
||||||
# Create user-supplied org user
|
# Enable URLScan.io Analyzer
|
||||||
curl -k -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/user" -d "{\"name\": \"$CORTEX_ORG_USER\",\"roles\": [\"read\",\"analyze\",\"orgadmin\"],\"organization\": \"$CORTEX_ORG_NAME\",\"login\": \"$CORTEX_ORG_USER\",\"key\": \"$CORTEX_ORG_USER_KEY\" }"
|
curl -v -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization/analyzer/Urlscan_io_Search_0_1_0" -d '{"name":"Urlscan_io_Search_0_1_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2}}'
|
||||||
|
|
||||||
# Enable URLScan.io Analyzer
|
# Enable Cert PassiveDNS Analyzer
|
||||||
curl -v -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization/analyzer/Urlscan_io_Search_0_1_0" -d '{"name":"Urlscan_io_Search_0_1_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2}}'
|
curl -v -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization/analyzer/CERTatPassiveDNS_2_0" -d '{"name":"CERTatPassiveDNS_2_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2, "limit": 100}}'
|
||||||
|
|
||||||
# Enable Cert PassiveDNS Analyzer
|
# Revoke $CORTEX_USER key
|
||||||
curl -v -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/organization/analyzer/CERTatPassiveDNS_2_0" -d '{"name":"CERTatPassiveDNS_2_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2, "limit": 100}}'
|
curl -k -XDELETE -H "Authorization: Bearer $CORTEX_KEY" -L "https://$CORTEX_API_URL/user/$CORTEX_USER/key"
|
||||||
|
|
||||||
# Revoke $CORTEX_USER key
|
# Update SOCtopus config with apikey value
|
||||||
curl -k -XDELETE -H "Authorization: Bearer $CORTEX_KEY" -L "https://$CORTEX_API_URL/user/$CORTEX_USER/key"
|
#sed -i "s/cortex_key = .*/cortex_key = $CORTEX_KEY/" $SOCTOPUS_CONFIG
|
||||||
|
|
||||||
# Update SOCtopus config with apikey value
|
touch /opt/so/state/cortex.txt
|
||||||
#sed -i "s/cortex_key = .*/cortex_key = $CORTEX_KEY/" $SOCTOPUS_CONFIG
|
else
|
||||||
|
echo "We experienced an issue connecting to Cortex!"
|
||||||
touch /opt/so/state/cortex.txt
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -f /opt/so/state/cortex.txt ]; then
|
if [ -f /opt/so/state/cortex.txt ]; then
|
||||||
cortex_clean
|
cortex_clean
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
rm -f garbage_file
|
if wait_for_web_response http://{{MANAGERIP}}:9400 '"status":"green"'; then
|
||||||
while ! wget -O garbage_file {{URLBASE}}:9500 2>/dev/null
|
cortex_init
|
||||||
do
|
cortex_clean
|
||||||
echo "Waiting for Elasticsearch..."
|
else
|
||||||
rm -f garbage_file
|
echo "TheHive Elasticsearch server is not ready; unable to proceed with cortex init."
|
||||||
sleep 1
|
fi
|
||||||
done
|
|
||||||
rm -f garbage_file
|
|
||||||
sleep 5
|
|
||||||
cortex_init
|
|
||||||
cortex_clean
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
# {%- set THEHIVEPASSWORD = salt['pillar.get']('global:hivepassword', 'hivechangeme') %}
|
# {%- set THEHIVEPASSWORD = salt['pillar.get']('global:hivepassword', 'hivechangeme') %}
|
||||||
# {%- set THEHIVEKEY = salt['pillar.get']('global:hivekey', '') %}
|
# {%- set THEHIVEKEY = salt['pillar.get']('global:hivekey', '') %}
|
||||||
|
|
||||||
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
thehive_clean(){
|
thehive_clean(){
|
||||||
sed -i '/^ hiveuser:/d' /opt/so/saltstack/local/pillar/global.sls
|
sed -i '/^ hiveuser:/d' /opt/so/saltstack/local/pillar/global.sls
|
||||||
sed -i '/^ hivepassword:/d' /opt/so/saltstack/local/pillar/global.sls
|
sed -i '/^ hivepassword:/d' /opt/so/saltstack/local/pillar/global.sls
|
||||||
}
|
}
|
||||||
|
|
||||||
thehive_init(){
|
thehive_init(){
|
||||||
sleep 120
|
|
||||||
THEHIVE_URL="{{URLBASE}}/thehive"
|
THEHIVE_URL="{{URLBASE}}/thehive"
|
||||||
THEHIVE_API_URL="$THEHIVE_URL/api"
|
THEHIVE_API_URL="$THEHIVE_URL/api"
|
||||||
THEHIVE_USER="{{THEHIVEUSER}}"
|
THEHIVE_USER="{{THEHIVEUSER}}"
|
||||||
@@ -20,23 +21,7 @@ thehive_init(){
|
|||||||
SOCTOPUS_CONFIG="/opt/so/saltstack/salt/soctopus/files/SOCtopus.conf"
|
SOCTOPUS_CONFIG="/opt/so/saltstack/salt/soctopus/files/SOCtopus.conf"
|
||||||
|
|
||||||
echo -n "Waiting for TheHive..."
|
echo -n "Waiting for TheHive..."
|
||||||
COUNT=0
|
if wait_for_web_response https://$THEHIVE_URL "TheHive"; then
|
||||||
THEHIVE_CONNECTED="no"
|
|
||||||
while [[ "$COUNT" -le 240 ]]; do
|
|
||||||
curl --output /dev/null --silent --head --fail -k "https://$THEHIVE_URL"
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
THEHIVE_CONNECTED="yes"
|
|
||||||
echo "connected!"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
((COUNT+=1))
|
|
||||||
sleep 1
|
|
||||||
echo -n "."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$THEHIVE_CONNECTED" == "yes" ]; then
|
|
||||||
|
|
||||||
# Migrate DB
|
# Migrate DB
|
||||||
curl -v -k -XPOST -L "https://$THEHIVE_API_URL/maintenance/migrate"
|
curl -v -k -XPOST -L "https://$THEHIVE_API_URL/maintenance/migrate"
|
||||||
|
|
||||||
@@ -48,7 +33,6 @@ thehive_init(){
|
|||||||
# reputation
|
# reputation
|
||||||
curl -v -k -L "https://$THEHIVE_API_URL/list/custom_fields" -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -d "{\"value\":{\"name\": \"reputation\", \"reference\": \"reputation\", \"description\": \"This field provides an overall reputation status for an address/domain.\", \"type\": \"string\", \"options\": []}}"
|
curl -v -k -L "https://$THEHIVE_API_URL/list/custom_fields" -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -d "{\"value\":{\"name\": \"reputation\", \"reference\": \"reputation\", \"description\": \"This field provides an overall reputation status for an address/domain.\", \"type\": \"string\", \"options\": []}}"
|
||||||
|
|
||||||
|
|
||||||
touch /opt/so/state/thehive.txt
|
touch /opt/so/state/thehive.txt
|
||||||
else
|
else
|
||||||
echo "We experienced an issue connecting to TheHive!"
|
echo "We experienced an issue connecting to TheHive!"
|
||||||
@@ -59,15 +43,10 @@ if [ -f /opt/so/state/thehive.txt ]; then
|
|||||||
thehive_clean
|
thehive_clean
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
rm -f garbage_file
|
if wait_for_web_response http://{{MANAGERIP}}:9400 '"status":"green"'; then
|
||||||
while ! wget -O garbage_file {{MANAGERIP}}:9400 2>/dev/null
|
thehive_init
|
||||||
do
|
thehive_clean
|
||||||
echo "Waiting for Elasticsearch..."
|
else
|
||||||
rm -f garbage_file
|
echo "TheHive Elasticsearch server is not ready; unable to proceed with hive init."
|
||||||
sleep 1
|
fi
|
||||||
done
|
|
||||||
rm -f garbage_file
|
|
||||||
sleep 5
|
|
||||||
thehive_init
|
|
||||||
thehive_clean
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ OSQUERY=1
|
|||||||
# PATCHSCHEDULEHOURS=
|
# PATCHSCHEDULEHOURS=
|
||||||
PATCHSCHEDULENAME=auto
|
PATCHSCHEDULENAME=auto
|
||||||
PLAYBOOK=1
|
PLAYBOOK=1
|
||||||
# REDIRECTHOST=
|
REDIRECTHOST=securityonion
|
||||||
REDIRECTINFO=HOSTNAME
|
REDIRECTINFO=OTHER
|
||||||
RULESETUP=ETOPEN
|
RULESETUP=ETOPEN
|
||||||
# SHARDCOUNT=
|
# SHARDCOUNT=
|
||||||
SKIP_REBOOT=0
|
SKIP_REBOOT=0
|
||||||
|
|||||||
@@ -1260,6 +1260,8 @@ manager_global() {
|
|||||||
"strelka:"\
|
"strelka:"\
|
||||||
" enabled: $STRELKA"\
|
" enabled: $STRELKA"\
|
||||||
" rules: 1"\
|
" rules: 1"\
|
||||||
|
" repos:"\
|
||||||
|
" - https://github.com/Neo23x0/signature-base"\
|
||||||
"curator:"\
|
"curator:"\
|
||||||
" hot_warm: False"\
|
" hot_warm: False"\
|
||||||
"elastic:"\
|
"elastic:"\
|
||||||
|
|||||||
Reference in New Issue
Block a user