Extracting Dynamic Values from Multiple Requests in a Nuclei Template

Introduction

We are using Nuclei for all the Security Automation tasks. We create a lot of custom templates to automate custom Authenticated APIs. A major challenge that we faced in automating this is dependence on dynamic variables. Site24x7's APIs have various dynamic entities that are dependent on other APIs for data. You can find Site24x7 Rest API reference. 

Problem Statement

Let's take this example for this blog. To automate monitor addition in Site24x7, we need to call a POST API "https://www.site24x7.com/api/monitors" with some body content. But, the problem is body content has so many dependencies which are dependent on other APIs. For example to call the above api, we need threshold_profile, notification_profile, user_group_id. So, to get these three values, we have to call the three apis sequentially extract the ids and pass it on to the Monitor Addition API.

Nuclei Extractors

https://nuclei.projectdiscovery.io/templating-guide/operators/extractors/

To achieve the above scenario, we worked on using the Nuclei Extractor and it worked really well but only for one dependent API. If we need to depend on dynamic variables for more than one API, this general extractor will not work, the dynamic value obtained in the first request will be replaced while calling the second request. 

How can we overcome this problem? 

Look at the below template. Here we make five Raw requests. The first 4requests are GET apis and the 5th one is the actual data api. The 5th api is dependent on one data from all the above 4 requests, and to achieve that you have to use "body_n" in the extractor, which will obtain the dynamic value from the nth request. By giving like this, the data in the dynamic variables will not get overwritten by subsequent requests.

 

requests:
   - raw:
       - |
         GET /app/api/user_groups HTTP/1.1
         Host: {{host}}
         Content-Type: application/json;charset=UTF-8
         Accept: application/json; version=2.1
         Authorization: Zoho-oauthtoken {{access_token}}

       - |
         GET /api/short/notification_profiles HTTP/1.1
         Host: {{host}}
         Accept: application/json; version=2.0
         Authorization: Zoho-oauthtoken {{access_token}}

       - |
         GET /api/location_profiles HTTP/1.1
         Host: {{host}}
         Accept: application/json; version=2.0
         Authorization: Zoho-oauthtoken {{access_token}}

       - |
         GET /api/short/threshold_profiles/PING HTTP/1.1
         Host: {{host}}
         Accept: application/json; version=2.0
         Authorization: Zoho-oauthtoken {{access_token}}

       - |
         POST /app/api/monitors HTTP/1.1
         Host: {{host}}
         Content-Type: application/json;charset=UTF-8
         Accept: application/json; version=2.1
         Authorization: Zoho-oauthtoken {{access_token}}

         {"type":"PING","check_frequency":"5","timeout":10,"use_ipv6":false,"threshold_profile_id":"{{threshold_id}}","location_profile_id":"{{location_id}}","tag_ids":[],"notification_profile_id":"{{notification_id}}","user_group_ids":["{{user_group_id}}"],"display_name":"ping","host_name":"192.168.98.23"}

     req-condition: true
     extractors:
          - type: json
            part: body_1
            name: user_group_id
            group: 1
            json:
              - '.data[[ .data[]  | .display_name == "Admin Group" ] | index(true)].user_group_id'
            internal: true

          - type: json
            part: body_2
            name: notification_id
            group: 1
            json:
              - '.data[0].id'
            internal: true

          - type: json
            part: body_3
            name: location_id
            group: 1
            json:
              - '.data[[ .data[]  | .profile_name == "United States" ] | index(true)].profile_id'
            internal: true

          - type: json
            part: body_4
            name: threshold_id
            group: 1
            json:
              - '.data[[ .data[]  | .name == "Default Threshold - PING" ] | index(true)].id'
            internal: true
   

 

Comments

Popular posts from this blog

Security Score Card using Nuclei Automation

How I used Nuclei to Automate Basic Security Checks