DEV Community

Michael Wahl for AWS Community Builders

Posted on

An intro to the Amazon Web Application Firewall

For anyone who is looking for a brief intro and overview on the ease and power of using AWS WAF.

Using a WAF is a great way to protect your web apps or APIs from common threats and other exploits, which in some way may affect confidentiality, integrity or availability.

Client Tools

To keep things super simple, I will be using a combination of curl commands and python to run a scan script.

Application for Testing

We will be testing the AWS WAF functionality by attaching it first to the OWASP Juice Shop app. If you are not familiar, the Juice Shop is an Open Source web application that is intentionally insecure. The Juice Shop is a great test app for those who are preparing to take the eJPT exam, or who are learning about other red team activities.

Deploying

I deployed the sample app using an AWS Cloud Formation Template.

Step by step instructions:
Give your stack a name
Click the "Next", using the default values
Click the Create stack button
CloudFormation will start the deployment, wait until all stacks are shown in a CREATE_COMPLETE state.

When the create is complete, find the JuiceShopUrl value in the CloudFormation template output, this is the address of your Juice Shop site.

Create new Web ACL under WAF, adding a managed rule group

Image description

export JUICESHOP_URL=<Your Juice Shop URL>

curl -X POST $JUICESHOP_URL -F "user='<script><alert>Hello></alert></script>'"

Lets create scanner.py , grab the code below which is also available to download.


# dependencies
import subprocess
import os
import sys

# used to color text
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    OTHER = '\033[95m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'


# validate command line
if len(sys.argv) != 2:
    print('Usage: scanner.py <target DNS or IP>')
    exit(1)

# set target dns
# target = sys.argv[1];
target = sys.argv[1].strip('/')

# parse HTTP request results
def parse_result(http_result):
    _http_result = ''.join(map(str, http_result))
    if  '403 Forbidden' in _http_result:
        return ('403 Forbidden' , 0)
    elif '200 OK' in _http_result:
        return ('200 OK' , 1)
    elif '404 Not Found' in _http_result:
        return ('404 Not Found' , 2)
    elif '500 Internal Server Error' in _http_result:
        return ('500 Server Error' , 3)
    else:
        return (_http_result , 4)

# tests to execute
tests = [
         {'Name': '--- Canary GET Request' , 'Type': 'Canary' , 'exec_string': "http -v " + target + "/index.php"},
         {'Name': '--- Canary POST Request', 'Type': 'Canary' , 'exec_string': "http -v --form POST " + target + "/index.php"},
         {'Name': '#1 SQLi in Query String' ,  'Type': 'SQLi' , 'exec_string': "http -v '" + target + "/product.php?id=-260479%2F**%2F%2F*!union*%2F%2F**%2F%2F*!select*%2F%2F**%2Fconcat(username%2C0x3a%2Cpassword%2C0x3a%2Cusertype)%2F**%2F%2F*!from*%2F%2F**%2Fjos_users%2F**%2F'"},
         {'Name': '#1 SQLi in Cookie' , 'Type': 'SQLi' ,  'exec_string': "http -v " + target + "/product.php?id=32574938 'Cookie:PHPSESSID=-260479%2F**%2F%2F*!union*%2F%2F**%2F%2F*!select*%2F%2F**%2Fconcat(username%2C0x3a%2Cpassword%2C0x3a%2Cusertype)%2F**%2F%2F*!from*%2F%2F**%2Fjos_users%2F**%2F'"},

         {'Name': '#1 XSS in Query String' , 'Type': 'XSS' , 'exec_string': "http -v '" + target + "/product.php?id=<script%20src%3D\"http%3A%2F%2F127.0.0.1%2Fxss_malware.js\">'"},
         {'Name': '#1 XSS in Body' , 'Type': 'XSS' , 'exec_string': "http -v --form POST " + target + " /product.php" + "reviewEmail=Hacker@Hacker.com reviewName=Hacker reviewTitle=Hacked reviewStory='<script>alert(\"Hello World!\")<script/>' reviewSubmit=Submit"},

         {'Name': '#2 Includes Modules' , 'Type': 'Includes' , 'exec_string': "http -v '" + target + "/includes/index.html'"},

         {'Name': '#3 CSRF Missing' , 'Type': 'CSRF' , 'exec_string': "http -v --form POST " + target + "/form.php" + " orderSubmit=Submit"},
         {'Name': '#3 CSRF Invalid' , 'Type': 'CSRF' , 'exec_string': "http -v --form POST " + target + "/form.php" + " orderSubmit=Submit  'x-csrf-token:b@d+0k3n198f3c998eb4c24cc168fd6b92b8c95a'"},

         {'Name': '#4 Path Traversal' , 'Type': 'Traversal' , 'exec_string': "http -v '" + target + "/download.php?form=..%2Fmodules%2Freviews.php'"}
        ]

print('##########################################################')
print('# WAF Tests on Target = ' + target)
print('##########################################################')

# list tests
line_width = 25
for single_test in tests:
    print("\nREQUEST: " + single_test['exec_string'])
    results =  subprocess.getstatusoutput(single_test['exec_string'])
    result_string , ret_code = parse_result(results)
    if ret_code == 1 and 'Canary' not in [single_test['Type']]:
        print(bcolors.FAIL  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    elif ret_code == 1 and "Canary" in single_test['Type']:
        print(bcolors.OKGREEN  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    elif ret_code == 0 and 'Canary' not in [single_test['Type']]:
        print(bcolors.OKGREEN  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    elif ret_code == 0 and "Canary" in single_test['Type']:
        print(bcolors.FAIL  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    elif ret_code == 2:
        print(bcolors.OKBLUE  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    elif ret_code == 3:
        print(bcolors.WARNING  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)
    else:
        print(bcolors.OTHER  + 'Test Name:' + single_test['Name'].ljust(line_width) + '  Result: ' + result_string + bcolors.ENDC)

Enter fullscreen mode Exit fullscreen mode

python3 scanner.py $JUICESHOP_URL

python3 scanner.py http://abc123.cloudfront.net or $JUICESHOP_URL

##########################################################
# WAF Tests on Target = http://abc123.cloudfront.net
##########################################################

REQUEST: http -v http://abc123.cloudfront.net/index.php
Test Name:--- Canary GET Request     Result: 403 Forbidden

REQUEST: http -v --form POST http://abc123.cloudfront.net/index.php
Test Name:--- Canary POST Request    Result: 403 Forbidden

REQUEST: http -v 'http://abc123.cloudfront.net/product.php?id=-260479%2F**%2F%2F*!union*%2F%2F**%2F%2F*!select*%2F%2F**%2Fconcat(username%2C0x3a%2Cpassword%2C0x3a%2Cusertype)%2F**%2F%2F*!from*%2F%2F**%2Fjos_users%2F**%2F'
Test Name:#1 SQLi in Query String    Result: 403 Forbidden

REQUEST: http -v http://abc123.cloudfront.net/product.php?id=32574938 'Cookie:PHPSESSID=-260479%2F**%2F%2F*!union*%2F%2F**%2F%2F*!select*%2F%2F**%2Fconcat(username%2C0x3a%2Cpassword%2C0x3a%2Cusertype)%2F**%2F%2F*!from*%2F%2F**%2Fjos_users%2F**%2F'
Test Name:#1 SQLi in Cookie          Result: 403 Forbidden

REQUEST: http -v 'http://abc123.cloudfront.net/product.php?id=<script%20src%3D"http%3A%2F%2F127.0.0.1%2Fxss_malware.js">'
Test Name:#1 XSS in Query String     Result: 403 Forbidden

REQUEST: http -v --form POST http://abc123.cloudfront.net /product.phpreviewEmail=Hacker@Hacker.com reviewName=Hacker reviewTitle=Hacked reviewStory='<script>alert("Hello World!")<script/>' reviewSubmit=Submit
Test Name:#1 XSS in Body             Result: 403 Forbidden

REQUEST: http -v 'http://abc123.cloudfront.net/includes/index.html'
Test Name:#2 Includes Modules        Result: 403 Forbidden

REQUEST: http -v --form POST http://abc123.cloudfront.net/form.php orderSubmit=Submit
Test Name:#3 CSRF Missing            Result: 403 Forbidden

REQUEST: http -v --form POST http://abc123.cloudfront.net/form.php orderSubmit=Submit  'x-csrf-token:b@d+0k3n198f3c998eb4c24cc168fd6b92b8c95a'
Test Name:#3 CSRF Invalid            Result: 403 Forbidden

REQUEST: http -v 'http://abc123.cloudfront.net/download.php?form=..%2Fmodules%2Freviews.php'
Test Name:#4 Path Traversal          Result: 403 Forbidden

Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
awsnewbietips profile image
AWS Newbie Tips 👩‍💻

Very nice indeed, would appreciate the cross post (with canonical URL of course) over at our AWS Newbies Tips forem 😎