Behold the Power of GraphQL

Written by Pete Corey on Jun 5, 2017.

Imagine you’re build out a billing history page. You’ll want to show the current user’s basic account information along with the most recent charges made against their account.

Using Apollo client and React, we can wire up a simple query to pull down the information we need:


export default graphql(gql`
    query {
        user {
            id
            email
            charges {
                id
                amount
                created
            }
        }
    }
`)(Account);

Question: Where are the user’s charges being pull from? Our application’s data store? Some third party service?

Follow-up question: Does it matter?

A Tale of Two Data Sources

In this example, we’re resolving the current user from our application’s data store, and we’re resolving all of the charges against that user with Stripe API calls.

We’re not storing any charges in our application.

If we take a look at our Elixir-powered Absinthe schema definition for the user type, we’ll see what’s going on:


object :user do
  field :id, :id
  field :email, :string
  field :charges, list_of(:stripe_charge) do
    resolve fn
      (user, _, _) ->
        case Stripe.get_charges(user.customer_id) do
          {:ok, charges} -> {:ok, charges}
          _ -> InjectDetect.error("Unable to resolve charges.")
        end
    end
  end
end

The id and email fields on the user type are being automatically pulled out of the user object.

The charges field, on the other hand, has a custom resolver function that queries the Stripe API with the user’s customer_id and returns all charges that have been made against that customer.

Keep in mind that this is just an example. In a production system, it would be wise to add a caching and rate limiting layer between the client and the Stripe API calls to prevent abuse…

Does It Matter?

Does it matter that the user and the charges agains the user are being resolves from different data sources? Not at all.

This is the power of GraphQL!

From the client’s perspective, the source of the data is irrelevant. All that matters is the data’s shape and the connections that can be made between that data and the rest of the data in the graph.

Have You Tried Just Using a Function?

Written by Pete Corey on May 29, 2017.

Last month I read Sasa Juric’s To Spawn, or Not to Spawn article and its been lurking in my subconscious ever since.

I was recently working on the command handler and event sourcing system that drives my new project, Inject Detect, and this exact topic reared its head. I realized that I had been overcomplicating the project with exessive usage of Elixir processes.

Refactoring my command handler from a process into simple functions hugely simplified the application, and opened the doors for a new set of functionality I wanted to implement.

The Command Handler Process

For a high level overview, a “command” in Inject Detect represents something you want to do in the system, like requesting a new sign-in token for a user (RequestSignInToken), or ingesting a batch of queries from a user’s application (IngestQueries).

Commands are “handled” by passing them to the command handler:


%IngestQueries{application_id: application.id, queries: queries}
|> CommandHandler.handle(command)

The job of the command handler is to determine if the command is allowable based on the state of the system and the current user’s authorizations. If valid, the command being handled (IngestQueries in this case) will produce a list of events (such as IngestedQuery and IngestedUnexpectedQuery). These events are saved to the database, and a handful of “event listeners” are notified.

Command Handler as a Process

Originally, the CommandHandler was implemented as a GenServer-based Elixir process. The call to CommandHandler.handle triggered a GenServer.call to the CommandHandler process:


def handle(command, context \\ %{}) do
  GenServer.call(__MODULE__, {:handle, command, context})
end

The corresponding handle_call callback would handle the command, store the resulting events, and synchronously notify any interested listeners:


def handle_call({:handle, command, context}, _, []) do
  with {:ok, events, context} <- handle_command(command, context),
       {:ok, _}               <- store_events(events),
  do
    notify_listeners(events, context)
    {:reply, {:ok, context}, []}
  else
    error -> {:reply, error, []}
  end
end

Triggering Commands from Listeners

For several weeks, this solution worked just fine. It wasn’t until I started adding more complex event listeners that I ran into real issues.

I mentioned earlier that event listeners are notified whenever an event is produced by a command. In some cases, these listeners may want to fire off a new command. For instance, when an IngestedUnexpectedQuery event is fired, a listener may want to execute a SendUnexpectedEmail command.

Implementing this feature blew up in my face.

Because listeners are called synchronously from my CommandHandler.handle function, another call to CommandHandler.handle from within a listener would result in a GenServer timeout.

The first call to CommandHandler.handle  won’t reply until the second CommandHandler.handle  call is finished, but the second CommandHandler.handle call won’t be processed until the first call finishes. The second call will wait until it hits its timeout threshold and eventually fail.

We’ve hit a deadlock.

The only way to handle this situation would be to execute either the second call to CommandHandler.handle, or the entire listener function within an unsupervised, asynchronous process:


Task.start(fn -> 
  %SendUnexpectedEmail{...}
  |> CommandHandler.handle
end)

I wasn’t willing to go down this road due to testing difficulties and a general distrust of unsupervised children.

Command Handler as a Function

After mulling over my deadlock problem, the solution slapped me in the face.

The functionality of the command handler could be entirely implemented as a module of simple functions. No process or GenServer required.

A quick refactor led me to this solution:


def handle(command, context, listeners) do
  with {:ok, events, context} <- handle_command(command, context),
       {:ok, _}               <- store_events(events)
  do
    notify_listeners(events, context, listeners)
    {:ok, context}
  end
end

After the refactor, a synchronously called event listener can recursively call CommandHandler.handle to handle any follow-up commands it wants to execute.

Perfect.

Have You Tried Just Using a Function?

In hindsight, I had no particular reason for implementing the CommandHandler module as a GenServer. It managed no state and had no specific concurrency concerns that demanded the use of a process.

When given a hammer, everything starts to look like a nail.

Remember to use the right tool for the job. In many cases, the right tool is the simplest tool. Often, the simplest tool for the job is to just use a function.

NoSQL Injection in Kadira

Written by Pete Corey on May 22, 2017.

Not long ago, the Meteor Development Group purchased Kadira after the Kadira team announced it would be shutting down. Shortly after, MDG open sourced the entire project on Github. 🎉

Being the curious developer that I am, I decided to sleuth through Kadira’s source looking for trouble.

I found several security issues which I reported to Meteor’s security team and were promptly fixed. Of those issues, the most notable was a NoSQL Injection vulnerability in Kadira’s user-facing kadira-ui Meteor application.

Let’s dive into the vulnerability and take a look at why it exists, how it could have been exploited, and how to prevent it.

Finding the Vulnerability

The best way to hit the ground running when looking for NoSQL Injection vulnerabilities in a Meteor application is to grep for calls to Meteor.methods, or Meteor.publish. This gives you a very quick idea of the entry points available to you as a user (or an attacker).

After finding all methods and publications, your next step is to peruse through every argument being passed into each method and publication and make sure that they’re being thoroughly checked.

In the kadira-ui project, I managed to find a Meteor method that wasn’t thoroughly checking its arguments. The "alerts.create" method was checking that the alertInfo argument matched Match.Any. Unfortunately, checking that an argument matches Match.Any is roughly equivalent to not checking it at all.

This is looking promising.

Tracing out the path of this method showed that alertInfo is passed into a function called setAppName. An appId field is pulled out of the alertInfo object and is ultimately passed directly into a MongoDB query:


var appId = alertsInfo.meta.appId;
var app = Apps.findOne(appId);

Passing an unchecked argument into a MongoDB query is the perfect recipe for a NoSQL Injection vulnerability.

Exploiting the Vulnerability

Because we, as intrepid explorers/malicious attackers, have complete control over the data passed into the Apps.findOne query, we’re presented with a few different choices in how we could exploit this vulnerability.

We could try to target a random application in the database by passing in a special MongoDB query operator when calling "alerts.create" from the client, like {_id: {$gte: ""}}:


Meteor.call("alerts.create", { meta: { appId: { _id: {$gte: ""} } } });

Or we could try something more impactful.

Because we have control over the entire query, we can pass in a $where query operator. The $where query operator is special in that it lets us pass in and execute raw Javascript in the MongoDB database process.

We can use this to our advantage to initiate a Denial of Service attack against the database and the Meteor application itself:


Meteor.call("alerts.create", {
    meta:{
        appId:{
            $where: "d = new Date; do {c = new Date;} while (c - d < 100000);"
        }
    }
});

In this example, we’re providing a query that will run a tight, unyielding loop for one hundred seconds per document in the Apps collection. It’s important to realize that this one hundred second time limit can be extended indefinitely or removed altogether.

We’ve essentially thrown the database into an infinite loop.

Pegging the CPU of the MongoDB host in this way drastically reduces the availability of the database and in many situations renders the Meteor application completely unusable.

With a single query, we’ve taken down the entire application.

Read more about the dangers of the $where query, and watch me exploit a similar vulnerability in my “NoSQL Injection in Modern Web Applications” talk given at CraterConf!

Fixing the Vulnerability

The fix for this specific instance of NoSQL Injection is to more thoroughly check the alertsInfo argument passed into the "alerts.create" method.

We’re expecting appId to be a String, so let’s check that it is:


check(alertInfo, Match.ObjectIncluding({
    meta: Match.ObjectIncluding({
        appId: String
    })
}));

If a malicious user provides anything other than a String (like a {$where: ...} query operator) in the appId field, our method will throw an exception.

Ideally, it would be better to fully flesh out the expected schema of alertInfo and avoid using Match.ObjectIncluding, but I’m not familiar enough with the application to make that change. In your application, you should check every field of every argument down to its primitive fields.

This change is enough to prevent a NoSQL Injection attack through the alertInfo.meta.appId field.

Even though Meteor isn’t actively maintaining their open sourced version of Kadira, I submitted a pull request to the project for posterity and to warn future users of the vulnerability.

Thanks to the Meteor Team

I’d like to give a huge shout out to the Meteor team for their speedy and professional response to this situation.

Nick Martin responded to my report within ten minutes and confirmed and patched my findings in their internal version of Kadira within twenty four hours.

Not only that, but they sent me a killer collection of swag!

I’d also like to thank MDG for swooping in during a time of crisis within the community, purchasing the Kadira platform, and open sourcing the entire product to the world. That act should be seen as no small gift to the Meteor community.

Inject Detect

If you’ve been following along for the past few months, you’ll know that I’m deep into the development of my security-focused project, Inject Detect.

Inject Detect is being developed to fight the exact problem I laid out in this article: NoSQL Injection. NoSQL Injection is an incredibly prevalent vulnerability in Meteor applications, and I’ve been fighting a war against it for years now.

Inject Detect is my newest and most powerful weapon to combat the threat of NoSQL Injection.

While Inject Detect is still under development, I’m fast approaching a releasable version. Be sure to sign up for the Inject Detect newsletter to stay up to date on its upcoming release!