Last active
June 25, 2021 08:39
-
-
Save cutaway/46b5e1df49071fa96e60 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Name: extract_java_server_faces_viewstate | |
Purpose: Extract and parse the Java Server Faces viewstate | |
Date: 20150620 | |
Author: Don C. Weber (@cutaway) of InGuardians, Inc. | |
Resources: | |
http://wiki.apache.org/myfaces/Secure_Your_Application | |
http://www.synacktiv.com/ressources/JSF_ViewState_InYourFace.pdf | |
https://github.com/frohoff/inyourface/blob/master/src/java/inyourface.java | |
https://prezi.com/t-lzwbqm2vwn/jsf-security/ - video shows fully encrypted viewstate value | |
TODO: | |
Identify if MAC has been enabled | |
Add functionality to grab a single page. For now just use Burp Suite. | |
""" | |
import urllib2 | |
import base64 | |
import gzip | |
from cStringIO import StringIO | |
import re | |
from copy import copy | |
import entropy as ent | |
def search_vs(data,relist = ['pass','user','secret','key']): | |
''' | |
Search parsed viewstate data for key terms | |
Inputs: | |
data: Parsed viewstate | |
relist: list of terms to search | |
''' | |
results = {} | |
for e in re.split(r'\x00*',data): | |
for n in relist: | |
if re.search(n,e): | |
if results.has_key(n): | |
results[n].append(e) | |
else: | |
results[n] = [e] | |
return results | |
def detect_vs(data,term = 'java'): | |
''' | |
Search parsed viewstate data for term that indicates unencrypted data | |
This test mimics SpiderLabs deface: https://github.com/SpiderLabs/deface | |
Inputs: | |
data: Parsed viewstate | |
term: term to use to detected unecrypted data | |
''' | |
for e in re.split(r'\x00*',data): | |
if re.search(term,e): | |
return True | |
return False | |
def extract_vs(data, param='value'): | |
''' | |
Extract a viewstate value from a line of HTML. | |
Inputs: | |
data: Single line of html with the viewstate parameter | |
param: the name of the viewstate parameter | |
''' | |
# Line will have spaces to separate values | |
for e in data.split(" "): | |
# Value will be separated by an "=" but only split on first occurrence | |
n = e.split("=",1) | |
# Viewstate should be the "value" parameter | |
if not n[0] == param: | |
continue | |
else: | |
# Remove quotes from beginning and end | |
# Returns base64 encoded viewstate | |
return n[1].replace("\"","") | |
return None | |
def parse_vs(data): | |
''' | |
Parse the viewstate data by decoding and unpacking it. | |
Inputs: | |
data: Single line of base64 encoded viewstate. URLENCODED data is okay | |
''' | |
# URL Encoding | |
urldelim = "%" | |
# Check to see if the viewstate data has urlencoded characters in it and remove | |
if re.search(urldelim,data): | |
d1 = urllib2.unquote(data).decode('utf8') | |
else: | |
d1 = copy(data) | |
# Base64 decode | |
d2 = base64.decodestring(d1) | |
# Generate a StringIO object since gzip wants a file descriptor | |
d3 = StringIO(d2) | |
# Decompress data | |
d4 = gzip.GzipFile(mode='rb', fileobj=d3) | |
# Get data from gzip file object | |
d5 = d4.read() | |
# Print viewstate and manually review for useful information | |
# Happy Hunting | |
return d5 | |
def print_vs(data): | |
''' | |
Print the viewstate by converting from 'iso-8859-1' to 'utf8' encoding | |
Inputs: | |
data: Single line of parsed viewstate | |
''' | |
print data.decode('iso-8859-1').encode('utf8') | |
if __name__ == "__main__": | |
''' | |
# Usages: | |
# Extract Viewstate values from Burp Request/Response Extract file | |
grep javax.faces.ViewState burp_requests_responses.txt > burp_requests_responses_viewstate.txt | |
# Print parsed viewstate | |
data = open("burp_requests_responses_viewstate.txt",'r').readlines() | |
for e in data: | |
tmp = vs.extract_vs(e) | |
if tmp: | |
print "\n============\n" | |
print repr(vs.parse_vs(tmp)) | |
print "\n============\n\n\n" | |
# Parse and search viewstate for key words | |
data = open("burp_requests_responses_viewstate.txt",'r').readlines() | |
for e in data: | |
tmp = vs.extract_vs(e) | |
if tmp: | |
results = vs.search_vs(vs.parse_vs(tmp)) | |
if results: | |
for v in results.keys(): | |
print v + ":",results[v] | |
print "\n===========\n\n" | |
''' | |
# Update "data" with data copied from viewstate | |
#d = "data" | |
d = sys.argv(1) | |
print parse_vs(d).decode('iso-8859-1').encode('utf8') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment