Why is your API insecure?

Source: Internet
Author: User

Why is your API insecure?

0 × 00 background

Some time ago, I reported to Spree Commerce about the JSONP + CSRF vulnerability in all its API paths. Similarly, the Instagram API has the CSRF vulnerability. The APIs of Disqus, Stripe, and Shopify leak private information through JSONP. The root cause of all these problems is the lack of rational use of hybrid API authentication.

I hope all API developers can take a look at this article. I will explain the basics of API authentication and the best practices in the industry.

0 × 01 detailed process

First, your API passes api_key authentication:

def load_user  @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s)end

At this time, someone asks you to enable CORS (Cross-Origin Resource Sharing) because they want to call your API through JS:

config.middleware.insert_before 0, "Rack::Cors" do      allow do            origins '*'            resource '*', :headers => :any, :methods => [:get, :post, :options]      endend

Apparently, your APIController contains skip_before_action: verify_authenticity_token. So why do you still need CSRF verification for API requests from Android apps?

Another developer hopes that you can add support for JSONP (JSON with Padding) because earlier Browsers Do not support CORS. Of course you think this is okay:

after_filter  :set_jsonp_formatdef set_jsonp_format     if params[:callback] && request.get?           self.response_body = "#{params[:callback]}(#{response.body})"           headers["Content-Type"] = 'application/javascript'     endend

At present, everything seems to be okay. Finally, your developers decide to follow the trend of Backend-As-API and use your api.example.com on the client. There are two options:

1. manually add api_token

For example, each API request header of Soundcloud uses Authorization: OAuth 1-16343-15233329-796b6b695d2c7c1 and Foursquare uses oauth_token = YXIAC4Y254HGZBNPQW6S0UFBGGSU57RBP.

Disadvantages:

1. XSS. OAuth tokens can be accessed through JS, which allows attackers to leak victim creden. You can use HttpOnly flag to prevent such events. However, OAuth tokens does not take such preventive actions.

2. Each request has an OPTIONS request, which increases the potential risk.

Although many people use this method, I do not recommend it.

Ii. User Authentication through cookie

As a result, the solution is simple:

@current_api_user = (try_spree_current_user || Spree.user_class.find_by(spree_api_key: api_key.to_s))

Try_spree_current_user parses _ spree_session cookie and returns user_id to User. find (session [: user_id]). So what are the problems with this approach?

Like Authorization, cookies are encapsulated in the header, but even experienced developers cannot really understand cookies. I call it "sticky credentials" because they are automatically added, even requests from third-party domains (such as evil.com ).

Because most web developers do not understand this concept, CSRF becomes the most common security issue in the world. This is also why all cookie-based authentication requires the use of additional csrf_token nonce for dual authentication. This nonce allows you to determine the request comes from your domain name.

1. Because CSRF protection is missing in your API request, all your API paths are at risk of request forgery. Example of Spree admin Password Change (http://securecanvas.com/csrf.html# {"url": "https://majestic-stall-2602.spree.mx/api/users/1", "autosubmit": false, "target": "_ top", "data ": "utf8 = % E2 % 9C % 93 & _ method = put & user % 5 Bemail % 5D = spree % 40example. com1 & user % 5Bspree_role_ids % 5D % 5B % 5D = & user % 5 Bpassword % 5D = 123123123 & user % 5Bpassword_confirmation % 5D = 123123123 & button = & sbmbtn = &", "method": "POST "}).

2. JSONP cross-site leakage GET response:

<script src="http://api.example.com/orders.json?callback=leakMe"></script>

3. CORS is even less reliable, and every request will leak information.

0 × 02 Solution

So how is this done? Hybrid API authentication:

@current_api_user = unless api_key.to_s.empty?  Spree.user_class.find_by(spree_api_key: api_key.to_s)  # Good to go!else  # Everyone stand back, we are using cookies!  # 1) verify CSRF token for all non-GET requests  # 2) drop JSONP support  # 3) drop CORS support  try_spree_current_userend

This hybrid method allows front-end (JS/HTML app) and third-party apps to use your api.example.com, so that your creden are not subject to XSS (HttpOnly) problems, there will be no unnecessary OPTIONS requests. The above is the best method in the industry.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.