Monthly Archives: September 2015

limit user bash shell with python

Simple use bdsh.py:

#!/usr/bin/python
# Copyright (C) 2013 - Remy van Elst

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see .

# This script can act as a shell for a user, allowing specific commands only.
# It tries its best to only allow those comamnds and strip possibly dangerous
# things like ; or >. But it won't protect you if you allow the vim command
# and the user executes !bash via vim (and such). It also logs everything to
# syslog for audit trailing purposes.

# It currently only checks commands, no parameters. This is on purpose.

import getpass, os, re, sys, syslog, signal, socket, readline

# format of whitelist: one command or regex per line
command_whitelist = "/etc/bdsh_whitelist.conf"
username = getpass.getuser()
hostname = socket.gethostname()

def log_command(command, status):
"""Log a command to syslog, either successfull or failed. """
global username
logline_failed = "[RESTRICTED SHELL]: user \"" + username + "\" NOT allowed for " + command
logline_danger = "[RESTRICTED SHELL]: user \"" + username + "\" dangerous characters in " + command
logline_success = "[RESTRICTED SHELL]: user \"" + username + "\" executed " + command
if status == "success":
syslog.syslog(logline_success)
elif status == "failed":
syslog.syslog(logline_failed)
elif status == "danger":
syslog.syslog(logline_danger)

def dangerous_characters_in_command(command):
# via http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
danger = [';', '&', '|', '>', '<', '*', '?', '`', '$', '(', ')', '{', '}', '[', ']', '!', '#'] for dangerous_char in danger: for command_char in command: if command_char == dangerous_char: return True def entire_command_scanner(command): danger = ["&&"] for dangerous_char in danger: if re.findall(dangerous_char, command): return True def execute_command(command): """First log, then execute a command""" log_command(command, "success") # try: # subprocess.call(command, shell=False) # except OSError: # pass os.system(command) def command_allowed(command, whitelist_file=command_whitelist): """Check if a command is allowed on the whitelist.""" try: with open(whitelist_file, mode="r") as whitelist: for line in whitelist: # We are reading commands from a file, therefore we also read the \n. if command + "\n" == line: return True else: continue except IOError as e: sys.exit("Error: %s" % e) def interactive_shell(): global username global hostname while True: prompt = username + "@" + hostname + ":" + os.getcwd() + " $ " try: if sys.version_info[0] == 2: command = raw_input(prompt) else: command = input(prompt) # Catch CRTL+D except EOFError: print("") sys.exit() if command == "exit" or command == "quit": sys.exit() elif command: if not entire_command_scanner(command): if command_allowed(command.split(" ", 1)[0]): for chars in command: if dangerous_characters_in_command(chars): log_command(command, "danger") # Don't let the user know via an interactive shell and don't exit command="" execute_command(command) if __name__ == "__main__": ## Catch CTRL+C / SIGINT. s = signal.signal(signal.SIGINT, signal.SIG_IGN) arguments = "" for args in sys.argv: if dangerous_characters_in_command(args): log_command(args, "danger") sys.exit() ## No Arguments? Then we start an interactive shell. if len(sys.argv) < 2: interactive_shell() else: ## Check if we are not launched via the local shell with a command (./shell.py ls) if sys.argv[1] and sys.argv[1] != "-c" and command_allowed(sys.argv[1].split(" ", 1)[0]) and not entire_command_scanner(sys.argv[1]): for arg in sys.argv[1:]: arguments += arg arguments += " " execute_command(arguments) ## Check if we are launched via the local shell and the command is not allowed elif len(sys.argv) < 3: for arg in sys.argv: arguments += arg arguments += " " log_command(arguments, "failed") elif sys.argv[2] and command_allowed(sys.argv[2].split(" ", 1)[0]) and not entire_command_scanner(sys.argv[2]): for arg in sys.argv[2:]: arguments += arg arguments += " " execute_command(arguments) else: for arg in sys.argv: arguments += arg arguments += " " log_command(arguments, "failed") # Debug use # print("\"" + arguments + "\"") ## Give back the CTRL+C / SIGINT signal.signal(signal.SIGINT, s)

ssmtp

SSMTP is a program which delivers email from a local computer to a configured mailhost (mailhub). It is not a mail server (like feature-rich mail server sendmail) and does not receive mail, expand aliases or manage a queue. One of its primary uses is for forwarding automated email (like system alerts) off your machine and to an external email address.

BGP Flow

The BGP flow specification (flowspec) feature allows you to rapidly deploy and propagate filtering and policing functionality among a large number of BGP peer routers to mitigate the effects of a distributed denial-of-service (DDoS) attack over your network.

In traditional methods for DDoS mitigation, such as RTBH (remotely triggered blackhole), a BGP route is injected advertising the website address under attack with a special community. This special community on the border routers sets the next hop to a special next hop to discard/null, thus preventing traffic from suspect sources into your network. While this offers good protection, it makes the Server completely unreachable.

BGP flowspec, on the other hand, allows for a more granular approach and lets you effectively construct instructions to match a particular flow with source, destination, L4 parameters and packet specifics such as length, fragment and so on. Flowspec allows for a dynamic installation of an action at the border routers to either:
Drop the traffic
Inject it in a different VRF for analysis or
Allow it, but police it at a specific defined rate