XMR Wallet Security Review

New Alchemy
Jul 17, 2018 · 27 min read

Xmr Wallet engaged New Alchemy to perform a security review of their XMRWallet web application shown in figure 1 below. The review was technical in nature and focused on identifying the susceptibility to security flaws in the application's behavior that may impact trustworthiness. The user interface and web traffic were inspected, along with a portion of the source code as dynamically delivered from the server at https://www.xmrwallet.com.

The review and test was performed in early June 2018. XMRWALLET.COM additionally provided access to the client-side application at https://github.com/XMRWallet/Website with a commit hash ofb03152135cf4577c320aae2ee51f9a6fae25437c. The private server-side API functionality, obfuscated client code and cryptography was out of scope. This document describes the issues discovered in the review.


The XMRWallet application exhibits a high-quality user experience, a modern development approach, and a clear separation of client and server functionality. However, the security review has identified a number of potential vulnerabilities. Given the nature of the application, these were conservatively rated in severity from critical to minor. All are believed to be fixable. Several examples include:

  • A cross-site scripting vulnerability stemming from the price feed
  • Outdated component dependencies on both the client and the server
  • Missing security-relevant headers as received from the server
  • Inadvisable display of private fields and input auto-completion
  • Potentially risky usage of JavaScript and HTML/DOM functionality

Re-test v2.0: XMRWallet’s audit response indicates that all critical issues reported by New Alchemy have been addressed.

Re-test v2.0: New Alchemy has inspected the application and repository provided for re-testing and believes that critical issues #1, #4, #5 and #7 have been fixed, critical issues #2 and #3 have been partially fixed, and critical issues #6 has not yet been fixed. Further details are included in the relevant sections below, including re-test notes for each of the other moderate and minor issues.

Re-test v2.1: New Alchemy has discussed the prior re-test results with XMRWallet, advised on efficient and effective mitigation approaches, inspected a subsequent application and repository provided for re-testing, and concludes:

  • All seven critical issues have been fixed and their risks mitigated.
  • Five of six moderate issues have been fixed and their risks mitigated. The remaining issue has been re-marked as ‘informational’ as it highlights a more general concern rather than a specific security issue.
  • Three of six minor issues have been fixed and their risks mitigated. Of the remaining three, one has been partially fixed and two have been re-marked as ‘informational’.
  • The net result is that all issues except one have been fixed or re-marked as ‘informational’. The remaining issue is minor, has been partially fixed and thus does not present a significant risk.

Supporting Files

src/js:
app.js jquery.i18n.js jquery.js select2.js
src/template:
account.twig index.twig login.twig receive.twig
create.twig landing.twig maintenance.twig send.twig
dashboard layout policy_login.twig support_login.twig
dashboard.twig login_public.twig policy.twig support.twig
terms_login.twig terms.twig transactions.twig

Re-test v2.0: New Alchemy has inspected the same repository with a new commit hash of 233ddd412d5a5afc877ba9dbab1524104767c338 under the same conditions noted above. The actual application under test was served from the same URL as noted above.

Re-test v2.1: New Alchemy has inspected the same repository with a new commit hash of abc0ab0a3d2c9cf587672ca03d80ade199e8e6ee under the same conditions noted above. The actual application under test was served from the same URL as noted above.

Figure 1: The https://www.xmrwallet.com Application

General Discussion

The client-side application has two clear portions. First, the ‘twig’ files noted above reside on the server and are dynamically delivered to the client as pages or portions of pages which contain some embedded page-specific JavaScript. Second, a variety of JavaScript components are assembled into app.js to provide the non page-specific functionality such as crypto.

The server-side application consists of numerous PHP API endpoints. This code and related functionality was out of scope. However, any relevant observations are noted in this report.

The primary client pages are listed below on the left. Server endpoints are listed on the right. Some server endpoints are extraneous (see Finding 17) and all were reachable via https://.

As the client-side application is dynamically delivered from the server and subsequently works in conjunction with out of scope server-side functionality, a full review would require complete source code of both sides. The dynamic nature of the application prevents stable hashes from being easily inspected by the user. Portions of obfuscated code represent out of scope black-boxes. Nonetheless, the client-side application’s behavior, user experience and web traffic can be robustly reviewed.

The review uncovered a number of findings ranging in severity from critical to minor. From inspecting the application, it appears that fixes will not require major code rip-up or drive fundamental architectural change. The resulting fixes will provide a significant uplift in application trustworthiness.

Critical Issues

1. Fixed: Insecure Auto-completion of Login Fields

Impact

Description and Discussion

The server returns the following snippet in response to a POST request to login.html.

...
<form id="login_account">
<div class="form-group">
<label class="label">
<span data-i18n="label_private_login_key">Your Seed:</span>
</label>
<input id="private_seed" type="text" class="form-control"
placeholder="Enter your Seed here"/>
</div>
...

An attacker is able to open up a fresh window and have the previous user’s seed provided as shown in figure 2 below.

Figure 2: Auto-completion of Seed Field

Remediation

Re-test v2.0: New Alchemy has inspected the application and has determined that this issue has been fixed and the associated risk mitigated. This was confirmed by inspecting the HTML fragment returned by login.html for the presence of an autocomplete="off" attribute, along with manually testing the function.

2. Fixed: Cross-Site Scripting Vulnerability

Impact

Description and Discussion

The exploitation of this vulnerability is outlined below:

The application makes a request to the price quote API endpoint at 
https://min-api.cryptocompare.com/data/price?fsym=XMR&tsyms=USD,BTC

The remote server API is expected to return a response of the form
{"USD":166.08,"BTC":0.02155}
HTML encoding an example payload of "XSS Injection Via CryptoCompare", including
the result inside of an malformed image tag onerror alert, and adjusting the API
return value gives:
{"USD":999,"BTC": "<img src=x onerror=alert(%22%58%53%53%20%49%6e%6a%65%63
%74%69%6f%6e%20%56%69%61%20%43%72%79%70%74%6f%43%6f%6d%70%61%72%65%22)>"}
When the above payload is presented to the application, it demonstrates the
resulting XSS exploitation shown in figure 3 below.

If the price feed service began to distinguish XMRWallet requests via its associated referer header and injected using the method shown above, the service could effectively break every user wallet at once. Additional background information on XSS can be found on OWASP's XSS Page.

Remediation

Canonicalization reduces input that may have several possible character representations into a standard character set (e.g. à á â ã a). Normalization reduces the input into its simplest possible form (e.g. ../../etc/passwd /etc/passwd). Sanitization eliminates unwanted characters and sequences from the input by means of recursively removing, replacing, encoding, or escaping the characters and sequences (e.g. <scr-<script>-ipt> scr-script-ipt). Validation ensures the input conform to the required schema and is consistent for use (e.g. alphanumeric only, 1+1=3). The collection of these stages are often loosely referred to as “validation” and their implementation can vary depending upon situational applicability.

In this specific instance, parsing expected values via a tightly constrained regex, validating it against expected ranges, and escaping the related output will be sufficient. Further work may be necessary on the server side as indicated by finding 4 below.

Re-test v2.0: New Alchemy has inspected the application and has determined that this issue has been partially fixed. The price data is now directly sourced from the application server via a new getprice.php endpoint rather than the third party service as originally noted. As such, it is no longer directly dependent upon the integrity of the third party pricing response, which is a large improvement. Note that New Alchemy does not have visibility into the new server-side endpoint sourcing or handling of the pricing data.

Re-test v2.0: However, the application continues to neglect validation of external input via the getprice.php response as originally noted. New Alchemy confirmed that modifying the response to contain {"USD":999,"BTC": "<img src=x onerror=alert(1)>"} still causes an XSS event. Best practices require that external input is not to be trusted or used prior to validation. The remediation advice of a tightly constrained regex validating input against expected ranges and escaping the related output remains strongly recommended.

Re-test v2.0: To be clear, New Alchemy considers the risk to be drastically reduced but not sufficiently eliminated to be considered fully fixed. An undiscovered scenario similar to that demonstrated in issue #4 below (OS Command Injection) on the server could result in the broadcast of malicious pricing data causing all user wallets to be completely compromised. Validating the pricing data as recommended would prevent this.

Re-test v2.1: New Alchemy has inspected the application and identified the new code which locally multiplies incoming price quotes by 1.0. As a result, (potentially malicious) strings no longer have a route into the DOM. While a minimalistic approach, it is sufficient to consider this issue fixed and the risk mitigated.

Figure 3: XSS Result

3. Fixed: Outdated Client-Side Application Dependencies

Impact

Description and Discussion

JavaScript is well known for the complexity of transitive dependencies — multiple versions of the same library can be loaded into memory simultaneously and reached via different execution paths. In addition, out of date dependencies can often be located at the end of a very long transitive chain. In some cases, build dependencies are mixed with test and deployment dependencies. Retire.js is a useful tool to check the freshness of dependencies.

The known CVE vulnerabilities from the dependencies listed above include:

This finding is categorized as critical due to the number of known CVEs and breadth of packages. The cross-site scripting exposure directly relates to finding 1. In this instance, updating dependencies is not expected to introduce functional breakage.

Remediation

Re-test v2.0: New Alchemy has inspected the application and has determined that this issue has been partially fixed. Due to the rapidly changing and deep transitive nature of nodeJs dependencies it is unrealistic to expect perfection. However, there remain several outdated packages that would greatly benefit from updating and thereby reduce CVE exposure. These include (see package.json):

Re-test v2.0:
"gulp-sass": "^3.2.1" ---> "gulp-sass": "^4.0.1"
"gulp-sass-image": "^1.0.2" ---> "gulp-sass-image": "^1.1.0"
"browserify": "^14.5.0" ---> "browserify": "^16.2.2"
"dialog-polyfill": "^0.4.9" ---> "dialog-polyfill": "^0.4.10"

Re-test v2.0: Please regularly re-run retire (see https://www.npmjs.com/package/retire) to uncover the use of vulnerable libraries and ensure the application remains up to date.

Re-test v2.1: New Alchemy has inspected the respository and considers this issue fixed and the risk mitigated.

4. Fixed: OS Command Injection

Impact

Description and Discussion

|ping -n 21 127.0.0.1||ping -c 21 127.0.0.1 #' |ping -n 21 127.0.0.1||ping -c 21 127.0.0.1 #" |ping -n 21 127.0.0.1

involving 21 second delays was submitted in the address parameter. The application took 21161 milliseconds to respond to the request, compared with 234 milliseconds for the original request. This is a clear indication that the injected command caused a time delay.

Figure 4 below shows the specific request made to the server API endpoint on the left. The corresponding server response text (which is not significant) is shown on the right. In the lower right corner, the tool significantly indicates 21161mS of round-trip delay which is far outside of normal response time.

Figure 4: OS Command Injection

Remediation

If it is considered unavoidable to incorporate user-supplied data into operating system commands, the following two layers of defense should be used to prevent attacks:

  • The user data should be strictly validated. Ideally, a whitelist of specific accepted values should be used. Otherwise, only short alphanumeric strings should be accepted. Input containing any other data, including any conceivable shell metacharacter or whitespace, should be rejected.
  • The application should use command APIs that launch a specific process via its name and command-line parameters, rather than passing a command string to a shell interpreter that supports command chaining and redirection. For example, the Java API Runtime.exec and the ASP.NET API Process.Start do not support shell metacharacters. This defense can mitigate the impact of an attack even in the event that an attacker circumvents the input validation defenses.
  • If more elaborate input must be accepted by the server, the validation process described in the remediation section of finding 2 should be employed.

Re-test v2.0: New Alchemy has inspected the application and was unable to recreate this issue as described above. Thus, it is considered fixed and the associated risk mitigated.

5. Fixed: Insufficient Server-Side Session Expiration

Impact

Description and Discussion

A browser session was initiated and the application exercised while using an intercepting proxy to record web traffic. The browser was then left idle until it auto-expired the session. The proxy was then used to successfully replay traffic with the original session credentials.

Figure 5 below shows the initial response from POST /getbalance.php on the left and a replayed version after browser session expiry on the right. The responses are identical with the exception of 33 minutes of elapsed idle time to test browser and server expiration logic consistency.

Figure 5: Non-Expired Session Balance

Figure 6 below shows a POST /gettransactions.php also replayed after session expiration. This leaks private transaction history details. No attempt was made to initiate malicious transactions due to project time constraints.

Figure 6: Non-Expired Session Transaction History

Remediation

Re-test v2.0: New Alchemy has inspected the application and determined this issue has been fixed and thus the associated risk mitigated. This was confirmed by initiating a valid session, waiting for the browser to timeout and then replaying prior requests to gettransactions.php and getbalance.php which did not return valid results.

6. Fixed: Missing Security Headers

Impact

Description and Discussion

  • Strict-Transport-Security This header supports confidentiality by helping to prevent HTTPS to HTTP protocol downgrade attacks.
  • X-Frame-Options This header supports authenticity by preventing content from being presented inside of frames on other sites.
  • X-XSS-Protection This header instructs the browser to inspect and analyze server responses to prevent reflected XSS.
  • X-Content-Type-Options This header instructs the browser to ‘make no guesses’ on interpreting malformed content.
  • Content-Security-Policy This header controls and constrains the resources allowed to load for a given page to prevent XSS.
  • ReferrerPolicy This header supports privacy by instructing the browser to not emit referer references when fetching content.
  • Cache-control: no-store (via login.html) This header instructs the browser not to cache sensitive content.
  • Pragma: no-cache (via login.html) This header also instructs the browser not to cache sensitive content.

The server presents none of the above headers to the browser as can be seen in figure 7 below.

Note that the absence of the ReferrerPolicy header increases the potential for attack in the second finding (XSS) above. OWASP provides a useful reference at their Secure Headers Project.

Remediation

Re-test v2.0: New Alchemy has inspected the application and confirmed that the headers listed above are now present on the response to GET ‘/’. However these headers are missing from the vast majority of other endpoints, including: (POST) /login.html, /send.html, /auth.php, /getbalance.php, /getprice.php and /gettransactions.php among others.

Re-test v2.1: New Alchemy has inspected the application and confirmed that appropriate headers are now present on each category of response (as static assets, GET .html and POST .php endpoints have slightly different requirements). This issue is considered fixed and the risk mitigated.

Figure 7: Server response from GET request to https//:www.xmrwallet.com

7. Fixed: Lack of Randomness in Ring Signature Outputs

Impact

Description and Discussion

Monero supports untraceability using a cryptographic primitive known as ring signatures. This allows a sender to anonymously sign a transaction on behalf of a set of other users. The real output being redeemed remains anonymous among outputs belonging to other users. Extensive analysis can be found in A Traceability Analysis of Monero’s Blockchain.

Repeated POST requests were made to /getrandomoutputs.php and the response contents inspected. Of the eight mix-in outputs returned, responses only differed by the insertion of one mix-in and the deletion of another.

Figure 8 below shows two separate responses side by side. The yellow highlighted mix-in public_key has been inserted. Figure 9 below also shows the same two responses side by side. The blue highlighted mix-in public_key has been deleted. There are no other differences beyond timestamps and a 1-byte difference in content length.

Figure 8: Two Random Output Responses; A Single public_key Addition
Figure 9: Two Random Output Responses; A Single public_key Deletion

Remediation

Re-test v2.0: New Alchemy has inspected the application and has determined that this issue has been fixed and the associated risk mitigated. This was confirmed by capturing a legitimate transaction to /getrandomoutputs.php, replaying it twice and confirming significant differences between server responses.

Moderate Issues

8. Fixed: Cookies not Destroyed Upon Logout

Impact

Description and Discussion

Figure 10: Cookies Remain After Logout

Remediation

Re-test v2.0: XMRWallet has correctly indicated that the _ga, _gat_gtag_UA_116766241_1 and_gid cookies are extraneous to the application functionality and it is unecessary to destroy them at logout. However, the xmrwalletidcookie is relevant and should be destroyed at logout. The original report paragraph lacks this necessary subtlety.

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue with respect to the xmrwalletid cookie. Thus, it is not yet fixed.

Re-test v2.1: XMRWallet has indicated that the xmrwalletid cookie is part of a desired 'remember-me' function and that the actual session id is destroyed in the browser at logout. New Alchemy has confirmed that the session id is present on the POST /logout.php request and then absent on the immediately subsequent POST login.html request. This issue is considered fixed and the risk mitigated.

9. Fixed: Non-Obfuscated Display of Private Fields

Impact

Description and Discussion

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed.

Re-test v2.1: New Alchemy has inspected the application and determined this issue has been fixed and thus the associated risk mitigated.

Figure 11: Non-Obfuscated Private Fields

10. Fixed: Missing Cookie Attributes

Impact

Description and Discussion

The HttpOnly attribute should be set as true to inform browsers that the session cookie should not be accessible via client-side JavaScript. If the attribute is set to false or missing, client-side JavaScript can read or set the cookie. If an application includes malicious third-party JavaScript or has a cross-site scripting vulnerability, the application could then disclose users’ session cookies to undesired parties or perform a Session Fixation attack. If an attacker is able to gain access to a user’s session cookie, the attacker could gain persistent access to that account.

The newly emerging Same Site attribute allows the server to advise the browser that cookies should only be sent if the request originates from the same web-site the cookie came from. Requests triggered from a URL different than the one that appears in the URL bar will not include any of the cookies tagged with this new attribute. This is primarily aimed at helping defend against cross-site request forgery (CSRF) attacks and is not yet broadly supported. The session cookie should utilize the Strict setting.

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed.

Re-test v2.1: New Alchemy has inspected the application for the presence of secure and httpOnly attributes, and determined this issue has been fixed and the associated risk mitigated. While the Same Site attribute is still not present, its absence is not considered critical due to its very limited browser support.

11. Informational: Potentially Unsafe JavaScript/HTML usage

Impact

Description

Extensive use of JavaScript == rather than ===. There are approximately 455 instances of the JavaScript ==abstract equality comparator in the code. While visually and conceptually similar, the == abstract comparator tests for loose equality which involves an automatic type coercion process. The === strict equality comparator is preferred as it uses simple strict equality without type coercion. This forces the developer to clearly anticipate types a priori and surfaces bugs early.

Twig Autoescaping. All data inserted into the DOM should be HTML escaped to prevent attacks including XSS. Twigprovides excellent support for the autoescaping process that relieves the developer from the minutia. No evidence of its use was observed.

Use of innerHTML. Grepping the code reveals multiple instances of innerHTML use. This is dangerous as HTML elements are evaluated, for example the text blah blah <img src=x onerror=alert(1)> blah blah can insert XSS JavaScript via the onerror attribute. See this Mozilla Article. The critical XSS finding 2 was injected via this exact route.

Remediation

  1. Utilize Twig autoescaping functionality to the maximum extent possible.
  2. Replace instances of innerHTML with the safer node.textContent

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Specifically a grep == run against the twig files returns significant usage. The same operation for innerHTML also returns several instances including lines relevant to critical issue #2 (XSS). Thus, it is not yet fixed.

Re-test v2.1: After further discussion with XMRWallet, New Alchemy agrees that this issue does not identify a current and specific security vulnerability. As it does highlight practices counter to industry norms, which in fact led to the existence of critical issue #2, it has been retained under an ‘Informational’ heading.

12. Fixed: Insufficient Session ID Entropy

Impact

Description and Discussion

FYI, A similar analysis was performed on the xmrwalletid cookie and entropy approaches 128 bits - excellent.

It is unclear how the two session IDs are utilized over the life-cycle of the application. This finding is written out of an abundance of caution.

Remediation

Re-test v2.0: Subsequent feedback indicates this finding was overly cautious as suggested above. New Alchemy considers this issue fixed and the associated risk mitigated.

13. Fixed: Server Discloses Directory Listing

Impact

Description and Discussion

Figure 12: Directory Contents

Remediation

Re-test v2.0: New Alchemy has inspected the application and has determined that this issue has been fixed and the associated risk mitigated.

Minor Issues

14. Partially-Fixed: Server Discloses Sensitive Information

Impact

Description and Discussion

The application notes that it is built upon Apache v2.4.18 in both the response header and body shown below.

HTTP/1.1 301 Moved Permanently
Date: Thu, 07 Jun 2018 13:02:09 GMT
Server: Apache/2.4.18 (Ubuntu)
Location: https://www.xmrwallet.com/
Content-Length: 317
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://www.xmrwallet.com/">here</a>.</p>
<hr>
<address>Apache/2.4.18 (Ubuntu) Server at www.xmrwallet.com Port 80</address>
</body></html>

Further, note that application API endpoints end with the .php suffix, which indicates PHP server technologies.

Remediation

Re-test v2.0: New Alchemy has inspected the application and observed that while server header no longer identifies the specific version of Apache, it still indicates Apache. The php suffixes remain on the API endpoints. Thus, this issue is not yet fully fixed.

Re-test v2.1: No change from prior status. New Alchemy believes the removal of the specific Apache version identifier mitigates the majority of risk associated with this finding, per the following issue below.

15. Fixed: Outdated server dependencies

Impact

Description and Discussion

Remediation

Re-test v2.0: New Alchemy has inspected the application and observed that the server header no longer identifies the specific version of Apache. Thus, this issue is fixed and the associated risk mitigated.

16. Informational: Lack of Attack Detection

Impact

Description and Discussion

While generating 2000 new sessions for entropy analysis, it was noted that the application does not implement lockout or rate limiting. It is common and recommended for an application to detect automated requests and report their presence as part of the health check functionality.

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed. Note that this type of functionality is often considered on a medium-term roadmap and XMRWallet would not stand out from competitors while this functionality is absent.

Re-test v2.1: After further discussion with XMRWallet, New Alchemy agrees that this issue does not identify a current and specific security vulnerability. As it does highlight desirable future functionality, it has been retained under an ‘Informational’ heading.

17. Fixed: Server Responds to Extraneous Endpoints

Impact

Description and Discussion

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed.

Re-test v2.1: In further discussion, XMRWallet has elaborated the intentional reason behind the server responses to the items listed. New Alchemy considers this issue fixed and the risk mitigated.

18. Informational: Potentially Extraneous/Misconfigured Cookie

Impact

Description and Discussion

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed. Note that this is essentially an informative issue.

Re-test v2.1: XMRWallet has indicated this issue to be an accepted risk. It has been marked as informational per the v2.0 statement above.

19. Fixed: URL Reflection

Impact

Description and Discussion

Input being returned in application responses is not a vulnerability in its own right. However, it is a prerequisite for many client-side vulnerabilities, including cross-site scripting, open redirection, content spoofing, and response header injection. Additionally, some server-side vulnerabilities such as SQL injection are often easier to identify and exploit when input is returned in responses. In applications where input retrieval is rare and the environment is resistant to automated testing (for example, due to a web application firewall), it might be worth subjecting instances of it to focused manual testing.

As shown in figure 10 below, the 404 page appears to be reflecting the URL request verbatim.

Figure 13: Request Reflected in Response

Remediation

Re-test v2.0: New Alchemy has inspected the application and was able to recreate this issue as described above. Thus, it is not yet fixed.

Re-test v2.1: XMRWallet has added a custom 404 page to remediate this issue. New Alchemy considers this issue fixed and the risk mitigated.


Limitation and Disclaimer

The server-side API code, obfuscated client code and cryptography was out of scope.


New Alchemy is a leading blockchain strategy and technology group specializing in tokenized capital solutions for the most innovative companies worldwide. New Alchemy’s Blockchain Security division is a highly trusted name that has assisted clients in securely raising over $500m through custom-tailored solutions, smart contract audits and comprehensive security strategy. Get in touch with us at Hello@NewAlchemy.io

New Alchemy

Analysis, updates, and education from the world's leading…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store