Coordinated Disclosure Timeline
- 2023-04-13: Asked the maintainer for a security contact.
- 2023-04-14: Got a response and sent report.
- 2023-04-20: Issue was fixed and advisory for CVE-2023-30614 was published.
Summary
Pay, a payments engine for Ruby on Rails, comes with a payment info page which was susceptible to Cross-site scripting. This allowed a remote attacker to execute JavaScript code in the context of the current user. An attacker could have used this vulnerability to execute requests in the name of a logged-in user or potentially collect information about the attacked user by displaying a malicious form.
Product
Pay
Tested Version
Details
Cross-site scripting in payments display page (GHSL-2023-084
)
A payments info page of Pay was susceptible to reflected Cross-site scripting. An attacker could have created a working URL that renders a javascript
link to a user on a Rails application that integrates Pay. This URL could have been distributed via email to specifically target certain individuals. If the targeted application contained a functionality to submit user-generated content (such as comments) the attacker could have even distributed the URL using that functionality.
In the show
method of the PaymentsController class, the user-controlled value of the parameter named back
is assigned to the instance variable named @redirect_to
:
@redirect_to = params[:back].presence || root_path
This value is then rendered using a link_to
helper function in the corresponding view (show.html.erb):
<%= link_to t("pay.back"), @redirect_to, [..]
The link_to
view helper does not check the protocol of the provided URL, this makes it possible to provide an URL starting with javascript:
.
This vulnerability was found using CodeQL’s reflected cross-site scripting query for Ruby.
Proof of Concept
Precondition: The attacker needs to know a valid Stripe Payment Intent ID for the targeted page. This Payment Intent ID doesn’t need to be newly created to work. (So the attacker can start a payment themselves and copy the payment intent ID.)
The attacker can then construct an URL such as:
http://<host-using-pay>/pay/payments/<PaymentIntentID>?back=javascript:alert(document.location)
E.g., such a URL could look like this:
http://127.0.0.1:3000/pay/payments/pi_3Mw23E2wqvxfBLhL1dzvJ3Xn?back=javascript:alert(document.location)
If an existing payment intent ID for the targeted site is used, the following text is displayed to the user “This payment was already successfully confirmed.”. Below this text a button is displayed that points to the JavaScript link of the attacker.
If a targeted user clicks on this link using the “Go back” button the JavaScript is executed in context of the actual website. This means the attacker can use the logged-in user to perform actions on their behalf.
Impact
This issue may lead to Sensitive data disclosure due to reflected Cross-site scripting (XSS).
Resources
Cross Site Scripting: link to HREF
CVE
- CVE-2023-30614
Credit
This issue was discovered and reported by GHSL team member @p- (Peter Stöckli).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-084
in any communication regarding this issue.