[JSWSERVER-5562] XSS (reflected) in rankVMID parameter of GetRankPage.jspa

          Reviewed again the code and removed this parameter entirely.

          JoanneA (Inactive) added a comment - Reviewed again the code and removed this parameter entirely.

          David Black added a comment - - edited

          To be honest I would fix this issue like the following:
          1. use Ajs.$ (jquery) 'on' event on the various a links with javascript targets in the velocity file and then call the Boards.searchFor - with the values for the Boards.searchFor set as attributes on the <a> element.

          e.g.

          diff -r 9f0ebd04e28f greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm
          --- a/greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm	Thu Nov 22 14:46:43 2012 +1100
          +++ b/greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm	Thu Nov 22 17:41:46 2012 +1100
          @@ -9,11 +9,11 @@
           				<span>
           					#if($action.selectedBoard.pagination.showStartPagine())
           						#if($action.selectedBoard.pagination.start == 0)<span class="active">$action.getText('gh.drop.startpagine')</span>
          -						#else<a href="javascript:Boards.searchFor('0', '$action.selectedBoard.strippedSearchKeyForInput', '${action.escapeJavaScript($action.searchType)}', '${action.escapeJavaScript($action.redirectType)}');">$action.getText('gh.drop.startpagine')</a>#end
          +						#else<a id="first_a_link_example" href="#" start='0' key='$action.selectedBoard.strippedSearchKeyForInput' searchType='${action.escapeJavaScript($action.searchType)}' redirectType='${action.escapeJavaScript($action.redirectType)}';">$action.getText('gh.drop.startpagine')</a>#end
           					#end
           					#foreach($page in $action.selectedBoard.pagination.pages)
           						#if($action.selectedBoard.pagination.isSelected($page))<span class="active">$page.pageNumber</span>
          -						#else<a href="javascript:Boards.searchFor('$page.start', '$action.selectedBoard.strippedSearchKeyForInput', '${action.escapeJavaScript($action.searchType)}', '${action.escapeJavaScript($action.redirectType)}');">$page.pageNumber</a>#end
          +						#else<a id="second_a_link_example" href="javascript:Boards.searchFor('$page.start', '$action.selectedBoard.strippedSearchKeyForInput', '${action.escapeJavaScript($action.searchType)}', '${action.escapeJavaScript($action.redirectType)}');">$page.pageNumber</a>#end
           					#end
           					#if($action.selectedBoard.pagination.showEndPagine())
           						#if($action.selectedBoard.pagination.lastPageSelected)<span class="selected">$action.getText('gh.drop.endpagine')</span>
          @@ -51,4 +51,13 @@
           		#end
           	</div>
           #end
          -<script type="text/javascript">GH.Util.hideAll(['opt_wait', 'Search_wait']);</script>
          +<script type="text/javascript">GH.Util.hideAll(['opt_wait', 'Search_wait']);
          +AJS.$.("first_a_link_example, second_a_link_example").on("click", function (event) {
          +    var _this = AJS.$(this);
          +    Boards.searchFor(this.attr('start'), this.attr('key'), this.attr('searchType'), this.attr('redirectType'));
          +
          +});
          
          +</script>
          

          David Black added a comment - - edited To be honest I would fix this issue like the following: 1. use Ajs.$ (jquery) 'on' event on the various a links with javascript targets in the velocity file and then call the Boards.searchFor - with the values for the Boards.searchFor set as attributes on the <a> element. e.g. diff -r 9f0ebd04e28f greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm --- a/greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm Thu Nov 22 14:46:43 2012 +1100 +++ b/greenhopper/src/main/resources/templates/greenhopper/jira/boards/searchboard/search-results.vm Thu Nov 22 17:41:46 2012 +1100 @@ -9,11 +9,11 @@ <span> # if ($action.selectedBoard.pagination.showStartPagine()) # if ($action.selectedBoard.pagination.start == 0)<span class= "active" >$action.getText( 'gh.drop.startpagine' )</span> - # else <a href= "javascript:Boards.searchFor( '0' , '$action.selectedBoard.strippedSearchKeyForInput' , '${action.escapeJavaScript($action.searchType)}' , '${action.escapeJavaScript($action.redirectType)}' );" >$action.getText( 'gh.drop.startpagine' )</a>#end + # else <a id= "first_a_link_example" href= "#" start= '0' key= '$action.selectedBoard.strippedSearchKeyForInput' searchType= '${action.escapeJavaScript($action.searchType)}' redirectType= '${action.escapeJavaScript($action.redirectType)}' ;">$action.getText( 'gh.drop.startpagine' )</a>#end #end #foreach($page in $action.selectedBoard.pagination.pages) # if ($action.selectedBoard.pagination.isSelected($page))<span class= "active" >$page.pageNumber</span> - # else <a href= "javascript:Boards.searchFor( '$page.start' , '$action.selectedBoard.strippedSearchKeyForInput' , '${action.escapeJavaScript($action.searchType)}' , '${action.escapeJavaScript($action.redirectType)}' );" >$page.pageNumber</a>#end + # else <a id= "second_a_link_example" href= "javascript:Boards.searchFor( '$page.start' , '$action.selectedBoard.strippedSearchKeyForInput' , '${action.escapeJavaScript($action.searchType)}' , '${action.escapeJavaScript($action.redirectType)}' );" >$page.pageNumber</a>#end #end # if ($action.selectedBoard.pagination.showEndPagine()) # if ($action.selectedBoard.pagination.lastPageSelected)<span class= "selected" >$action.getText( 'gh.drop.endpagine' )</span> @@ -51,4 +51,13 @@ #end </div> #end -<script type= "text/javascript" >GH.Util.hideAll([ 'opt_wait' , 'Search_wait' ]);</script> +<script type= "text/javascript" >GH.Util.hideAll([ 'opt_wait' , 'Search_wait' ]); +AJS.$.( "first_a_link_example, second_a_link_example" ).on( "click" , function (event) { + var _this = AJS.$( this ); + Boards.searchFor( this .attr( 'start' ), this .attr( 'key' ), this .attr( 'searchType' ), this .attr( 'redirectType' )); + +}); +</script>

          I believe what you really want is for it to be jsencoded when it is put into js strings and and in some cases additionally html encoded. The current fix will mean the js is passed an incorrect id. Things inside script tags dont need html encoding, only javascript string escaping

          jhinch (Atlassian) added a comment - I believe what you really want is for it to be jsencoded when it is put into js strings and and in some cases additionally html encoded. The current fix will mean the js is passed an incorrect id. Things inside script tags dont need html encoding, only javascript string escaping

          vosipov I am not convinced that the fix is the 'best' way to fix the issue. I'll look at the velocity file some more shortly in regards to this issue.

          David Black added a comment - vosipov I am not convinced that the fix is the 'best' way to fix the issue. I'll look at the velocity file some more shortly in regards to this issue.

          VitalyA added a comment -

          dblack, please have a quick look at the vm template.

          VitalyA added a comment - dblack , please have a quick look at the vm template.

          The fix for this bug was in the velocity template which is not unit-testable - discussed with mtokar and agreed not to create a webdriver test.

          JoanneA (Inactive) added a comment - The fix for this bug was in the velocity template which is not unit-testable - discussed with mtokar and agreed not to create a webdriver test.

          Checked in on branch GHS-5562. Please test with GHS-6705.

          Changed from using escapeJavaScript to htmlEncode - this ensures that all characters are encoded including ", <, > rather than just prefixed with \ which is safer for using inside html attributes.

          JoanneA (Inactive) added a comment - Checked in on branch GHS-5562 . Please test with GHS-6705 . Changed from using escapeJavaScript to htmlEncode - this ensures that all characters are encoded including ", <, > rather than just prefixed with \ which is safer for using inside html attributes.

          How to reproduce this bug:

          This occurs in the rendering of a list of issues on this page. If you try to access a similar URL and see a message reading "Not Authorised" or "No Issues Found" then you will not see the problem.

          It can be reproduced on a local instance.

          To get a URL to work locally, change the host name and then make the fieldId the id of the Rank custom field, and ProjectId a valid project ID with some issues.

          Using the usual GH dataset, fieldId=customfield_10004 and projectId=10703 works to reproduce (anonymous project).

          JoanneA (Inactive) added a comment - How to reproduce this bug: This occurs in the rendering of a list of issues on this page. If you try to access a similar URL and see a message reading "Not Authorised" or "No Issues Found" then you will not see the problem. It can be reproduced on a local instance. To get a URL to work locally, change the host name and then make the fieldId the id of the Rank custom field, and ProjectId a valid project ID with some issues. Using the usual GH dataset, fieldId=customfield_10004 and projectId=10703 works to reproduce (anonymous project).

          This issue was not actually fixed. Simply the specific payload being supplied as reflected html was broken.
          The latest isec report provides the following url to test this issue (with an updated payload):

          https://test01.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=fielddd491"><img src=u onerror=alert(1)>060025152f2db6800&decorator=none&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          This attack still works in greenhopper 6.0.6.

          David Black added a comment - This issue was not actually fixed. Simply the specific payload being supplied as reflected html was broken. The latest isec report provides the following url to test this issue (with an updated payload): https://test01.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=fielddd491 "><img src=u onerror=alert(1)>060025152f2db6800&decorator=none&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1 This attack still works in greenhopper 6.0.6.

          In agreement with Jason, I can no longer reproduce this vulnerability on FF. Marking this as done.

          Peter Obara added a comment - In agreement with Jason, I can no longer reproduce this vulnerability on FF. Marking this as done.

          dblack

          fourwives:greenhopper jhinch$ hg log -r 10262
          changeset:   10262:4c3a4cc6f710
          branch:      GHS-4921-sample-data
          parent:      10261:3ad68507bd28
          parent:      10241:1bc502cacf19
          user:        James Hatherly <jhatherly@atlassian.com>
          date:        Tue Aug 21 16:58:38 2012 +1000
          summary:     merged in jim installer branch
          

          That isn't default and I doubt the fix is on that branch. If you can reproduce against default please let me know.

          fourwives:greenhopper jhinch$ hg log -r default
          changeset:   10258:536b752e4cde
          parent:      10250:ba271731c998
          parent:      10257:08d0d0f20d3a
          user:        Michael Tokar <mtokar@atlassian.com>
          date:        Tue Aug 21 16:17:56 2012 +1000
          summary:     merge GHS-5543-multi-sprint into default
          

          jhinch (Atlassian) added a comment - dblack fourwives:greenhopper jhinch$ hg log -r 10262 changeset: 10262:4c3a4cc6f710 branch: GHS-4921-sample-data parent: 10261:3ad68507bd28 parent: 10241:1bc502cacf19 user: James Hatherly <jhatherly@atlassian.com> date: Tue Aug 21 16:58:38 2012 +1000 summary: merged in jim installer branch That isn't default and I doubt the fix is on that branch. If you can reproduce against default please let me know. fourwives:greenhopper jhinch$ hg log -r default changeset: 10258:536b752e4cde parent: 10250:ba271731c998 parent: 10257:08d0d0f20d3a user: Michael Tokar <mtokar@atlassian.com> date: Tue Aug 21 16:17:56 2012 +1000 summary: merge GHS-5543-multi-sprint into default

          Testing the following path produced no issues for me:
          /secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1
          David Black [Atlassian] can provide a URL for which you are still seeing this issue. We appreciate your effort.
          Thanks

          jhinch That exact url still works (do not test this in chrome use firefox) tested against 10262:4c3a4cc6f710 on wpad.jira-dev.com.

          David Black added a comment - Testing the following path produced no issues for me: /secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1 David Black [Atlassian] can provide a URL for which you are still seeing this issue. We appreciate your effort. Thanks jhinch That exact url still works ( do not test this in chrome use firefox ) tested against 10262:4c3a4cc6f710 on wpad.jira-dev.com.

          Testing the following path produced no issues for me:
          /secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          dblack can provide a URL for which you are still seeing this issue. We appreciate your effort.

          Thanks

          jhinch (Atlassian) added a comment - Testing the following path produced no issues for me: /secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1 dblack can provide a URL for which you are still seeing this issue. We appreciate your effort. Thanks

          pobara asked me to test the latest default (I tested a snapshot I built on my desktop off 'default' – this included b8b52429a450239bfe6e1b02c904df78b6483c2d ) and this issue was not fixed.

          David Black added a comment - pobara asked me to test the latest default (I tested a snapshot I built on my desktop off 'default' – this included b8b52429a450239bfe6e1b02c904df78b6483c2d ) and this issue was not fixed.

          Found a bunch of other XSS issues on the classic boards. Did my best to clean them up

          jhinch (Atlassian) added a comment - Found a bunch of other XSS issues on the classic boards. Did my best to clean them up

          Peter Obara added a comment - Reopening as not all XSS injections have been escaped, and attributes can be injected into html elsewhere in the document. refer to: https://wpad.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          There are two injection points in GetRankPage.jspa through rankVMID one was in a javascript context and the other is attribute injection in an li element on the page. To illustrate the second injection point here is an example reflected xss url https://wpad.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          and here is the html where the attribute injection is found in (the onmouseover attribute is injected so that when moves their mouse over the li contents an alert prompt with the number 33 is displayed):

          <li title="Move before" onmouseout="AJS.$('#rank_FFFFFFFF-2').removeClass('gh-rank-movebefore');" x="');" onmouseover="alert(33)" onerror="alert(3)" onclick="Ranking.setRank('', '', 'customfield_10006', 'FFFFFFFF-2', 'Before FFFFFFFF-2', 'FFFFFFFF-2', '" style="background-color:#c00;" class="gh-rank-item" id="rank_FFFFFFFF-2">
                              <span class="gh-colour"></span>
                                                  <strong>FFFFFFFF-2</strong>
                              fffff
                          </li>
          

          David Black added a comment - There are two injection points in GetRankPage.jspa through rankVMID one was in a javascript context and the other is attribute injection in an li element on the page. To illustrate the second injection point here is an example reflected xss url https://wpad.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=%22%20onerror=alert(3)%20onmouseover=alert(33)%20%20x=%22&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1 and here is the html where the attribute injection is found in (the onmouseover attribute is injected so that when moves their mouse over the li contents an alert prompt with the number 33 is displayed): <li title= "Move before" onmouseout= "AJS.$( '#rank_FFFFFFFF-2' ).removeClass( 'gh-rank-movebefore' );" x= " ');" onmouseover= "alert(33)" onerror= "alert(3)" onclick= "Ranking.setRank(' ', ' ', ' customfield_10006 ', ' FFFFFFFF-2 ', ' Before FFFFFFFF-2 ', ' FFFFFFFF-2 ', ' " style= "background-color:#c00;" class= "gh-rank-item" id= "rank_FFFFFFFF-2" > <span class= "gh-colour" ></span> <strong>FFFFFFFF-2</strong> fffff </li>

          Already merged to default, thus closing

          Peter Obara added a comment - Already merged to default, thus closing

          Peter Obara added a comment - This is still exploitable, with content going inside some javascript. https://wpad.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=field%27;alert%281%29;/*%22/%3E%3C/script%3E%3Cscript%3Ealert%281%29%3C/script%3E&decorator=none&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          Peter as you are looking at the other XSS bug can you also look at this one.

          Its pretty embarassing for the team that we said we fixed it and we didnt so lets tighten up the QA on this one.

          ɹǝʞɐq pɐɹq added a comment - Peter as you are looking at the other XSS bug can you also look at this one. Its pretty embarassing for the team that we said we fixed it and we didnt so lets tighten up the QA on this one.

          branch -> GHS-5562-classic-board-xss. I also did an audit of other velocity templates. It doesn't look like there are any more similar situations (failing to encode values for JavaScript strings).

          jhinch (Atlassian) added a comment - branch -> GHS-5562 -classic-board-xss. I also did an audit of other velocity templates. It doesn't look like there are any more similar situations (failing to encode values for JavaScript strings).

          I was able to reproduce this issue against greenhopper 6.0.1.
          jhinch && jhatherly@atlassian.com if you need help in reproducing this issue please let me know.

          I tested an ondemand instance (fireball-164) running with greenhopper 6.0.1
          I tested the following url in firefox 14.0.1 and was able to trigger an alert prompt -->

          https://example.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=field%22%3E%3C/script%3E%3Cscript%3Ealert%28%27iSEC%27%29%3C/script%3E&decorator=none&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          David Black added a comment - I was able to reproduce this issue against greenhopper 6.0.1. jhinch && jhatherly@atlassian.com if you need help in reproducing this issue please let me know. I tested an ondemand instance (fireball-164) running with greenhopper 6.0.1 I tested the following url in firefox 14.0.1 and was able to trigger an alert prompt --> https://example.jira-dev.com/secure/GetRankPage.jspa?fieldId=customfield_10006&start=0&versionId=-1&rankVMID=field%22%3E%3C/script%3E%3Cscript%3Ealert%28%27iSEC%27%29%3C/script%3E&decorator=none&selectedProjectId=10000&pageType=ChartBoard&subType=ArchiveChartBoard&type=ACB&selectedBoardId=-1&colPage=1

          CVSS score: 7.5 => High severity
           
          Exploitability Metrics

          AccessVector Network
          AccessComplexity Low
          Authentication None

           
          Impact Metrics

          ConfImpact Partial
          IntegImpact Partial
          AvailImpact Partial

          See https://extranet.atlassian.com/display/SECCOUNCIL/How+to+evaluate+vulnerability+severity+under+CVSS for details and http://nvd.nist.gov/cvss.cfm?calculator&adv&version=2 for score calculator.

          David Black added a comment - CVSS score: 7.5 => High severity   Exploitability Metrics AccessVector Network AccessComplexity Low Authentication None   Impact Metrics ConfImpact Partial IntegImpact Partial AvailImpact Partial See https://extranet.atlassian.com/display/SECCOUNCIL/How+to+evaluate+vulnerability+severity+under+CVSS for details and http://nvd.nist.gov/cvss.cfm?calculator&adv&version=2 for score calculator.

            Unassigned Unassigned
            dblack David Black
            Affected customers:
            0 This affects my team
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: