> For the complete documentation index, see [llms.txt](https://documentation.hak5.org/packet-squirrel-mark-ii/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.hak5.org/packet-squirrel-mark-ii/advanced-payloads/processing-json.md).

# Processing JSON

## JSON basics

JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write and easy for machines to parse and generate. It's a text-based format that uses a simple syntax to represent data objects in a hierarchical structure.&#x20;

JSON documents consist of key-value pairs, where each key is a string and the value can be a string, number, boolean, null, array, or another JSON object.

JSON is widely used for transmitting data between web servers and clients, as well as for storing data in databases and files. It is a popular alternative to XML because it is simpler and more compact, making it easier to parse and generate.

JSON documents are often used in web development for AJAX (Asynchronous JavaScript and XML) applications, which allow web pages to update content dynamically without reloading the entire page. JSON is also commonly used in web APIs for exchanging data between different systems.

JSON documents can be an excellent way to store configuration values:

```json
{
    "option1": "some value",
    "option2": "some other value",
    "timeout": 10
}
```

## Parsing JSON from payloads

Payloads can process JSON using the `jshn` tool. &#x20;

`jshn` is a simple way to create and process JSON files, and is built into the Packet Squirrel.

### Including jshn in a payload

`jshn` is included using the `source` command in Bash.  This is a feature we have not covered before:  The `source` command (or simply `.` ) includes another script and interprets it immediately.  If you are familiar with other programming languages, this is similar to an `include`, `use`, or `import` statement.

```bash
#!/bin/bash

# Title: JSON processing
#
# Description: A JSON processing demo

# Include the system jshn library
. /usr/share/libubox/jshn.sh

# Set default netmode
NETMODE NAT
```

By importing the `jshn` library from the system, we now have access to a new set of functions for processing JSON files.

### Initializing the library

Before doing anyting else, `jshn` should be initialized.  This is simply:

```bash
json_init
```

This ensures no partial JSON data is held.

### Loading data

To use a JSON document via `jshn` first it has to be loaded with `json_load`.  This function parses the JSON and prepares it for all the other functions.

```bash
json_load "the-raw-json-string"
```

Content can also be loaded from a file, using the `json_load_file` function:

```bash
json_load_file /tmp/some-json-file.json
```

### Getting basic data

At the simplest, `jshn` allows us to extract content from a JSON document.  The `json_get_var` function takes two arguments:  the name of the variable to fill, and the name of the JSON field to fetch.

Putting this together with the previous examples:

```bash
#!/bin/bash

. /usr/share/libubox/jshn.sh

# Define an example JSON.  Notice how we use a 
# single quoted string here!
JSON='{"user": "timmy", "retries": 10}'

# Initialize json handling
json_init

# Load our JSON string
json_load "$JSON"

# Extract the two variables               
json_get_var uservar "user"
json_get_var retriesvar "retries"

echo $uservar $retriesvar
```

{% hint style="info" %}
Notice the use of single quotes when defining static JSON here:  This keeps Bash from interpreting the braces and quotes. See the [Quotes and Expansions](/packet-squirrel-mark-ii/advanced-payloads/quotes-and-expansions.md) chapter for more information.
{% endhint %}

### Getting complex data

`jshn` can parse more complex documents as well, of course.

You can navigate into nested objects with the `json_select {name}` function, and navigate to the previous level of the document with `json_select ..`&#x20;

For example, given a more complex JSON document:

```json
{
    "config": {
        "user": "test",
        "host": "some-test-host"
    },
    
    "retries": 10
}
```

We could then extract values using `jshn` via:

```bash
#!/bin/bash

. /usr/share/libubox/jshn.sh

json_init
json_load_file test.json

# Select the "config" object
json_select "config"

# Load variables from inside "config"
json_get_var uservar "user"
json_get_var hostvar "host"

# Leave the "config" object
json_select ..

# Get "retries" from the top object
json_get_var retryvar "retries"

echo "user: ${uservar}"
echo "host: ${hostvar}"
echo "retries: ${retryvar}"
```

### Handling multiple objects

Since JSON can contain arrays, `jshn` provides methods for iterating over lists of items.  The function `json_for_each_item` takes the name of a function and the JSON value, and calls that function for each value.

Given an example JSON with a list of URLs to fetch in a payload:

```json
{
    "urls":  [
        "https://host1.fake/file1", 
        "https://host2.fake/file2", 
        "https://host3.fake/file3"
    ]
}
```

We could then fetch each file with:

<pre class="language-bash"><code class="lang-bash">#!/bin/bash

. /usr/share/libubox/jshn.sh

<strong>function fetch_file() {
</strong>    wget "$1"
}

json_init
json_load_file urls.json

json_for_each_item fetch_file "urls"
</code></pre>

### Loading JSON from the web

As one of the main places JSON is used is in web services, it would be nice if we could load our JSON data directly.

Fortunately, this is (of course) possible!

To accomplish this, we combine `jshn` with `wget`.

```bash
#!/bin/bash

. /usr/share/libubox/jshn.sh

json_init
json_load "$(wget -O - https://random.host/test.json 2>/dev/null)"
```

Here we combine `wget` outputting to `stdout`, suppress the status by sending `stderr` to `/dev/null`, and we use the `$(..)` construct to retrieve the output of `wget`.

{% hint style="info" %}
Notice how we enclosed the `wget` command in quotes!  This is vital; otherwise spaces and other special characters in the returned data will break the JSON parsing.
{% endhint %}

## Creating JSON in payloads

The `jshn` tool can also be used to *create* JSON files. &#x20;

Creating a JSON file can be useful for saving states, or creating requests to API endpoints that expect JSON.

You can, of course, create JSON manually:

```bash
#!/bin/bash

uservar="mary"
retryvar=10
url1="https://fake.host/file1"
url2="https://fake.host/file2"

cat <<EOF
{
    "user": "${uservar}",
    "retries": "${retryvar}",
    "urls": ["${url1}", "${url2}"]
}
EOF
```

In simpler payloads, manually creating JSON may make the most sense.

### jshn creation functions

For more complex payloads and JSON documents, using the `jshn` creation framework can eliminate common trouble spots and simplify creating elements like arrays.

`jshn` provides several creation functions:

* `json_add_object` to create a JSON object or dictionary (balanced by `json_close_object`)
* `json_add_array` to create a JSON array (balanced by `json_close_array`)
* `json_add_boolean` to create a true/false value
* `json_add_int` to create a number
* `json_add_string` to create a string
* `json_dump` to create the JSON itself

Lets recreate the document above using `jshn` functions:

<pre class="language-bash"><code class="lang-bash"><strong>. /usr/share/libubox/jshn.sh
</strong>#!/bin/bash

uservar="mary"
retryvar=10
url1="https://fake.host/file1"
url2="https://fake.host/file2"

json_init

json_add_string "user" "${uservar}"
json_add_int "retries" "${retryvar}"

# Start the array
json_add_array "urls"

# Add strings to it
json_add_string "" "${url1}"
json_add_string "" "${url2}"

# Finish the array
json_close_array

# Print the JSON
json_dump
</code></pre>

This would print out the JSON string:

```json
{ "user": "mary", "retries": 10, 
    "urls": [ "https:\/\/fake.host\/file1", 
              "https:\/\/fake.host\/file2" ] }
```

### Bringing it all together

For a complete example, we'll create a payload that goes into `BRIDGE` mode then fetches a list of ports and filters to monitor.

We'll use this as our configuration JSON file, hosted on a server:

```json
{
    "ledcolor": "B",
    "ledpattern": "FAST",
    "streams": [
        {"port": 80, "match": "Basic Authentication"},
        {"port": 80, "match": "Potato"},
        {"port": 12345, "match": "Something else"}
    ]
}
```

To handle this, we'll put together several examples so far.  Our payload might look like:

```bash
#!/bin/bash

# Title: JSON Streamwatch
#
# Description: Pull data from JSON for streams

. /usr/share/libubox/jshn.sh

# Set network mode
NETMODE BRIDGE

# Wait 10 seconds to get an IP
sleep 10

# Initialize jshn
json_init

# Fetch our JSON
json_load "$(wget -O - https://random.host/payload.json 2>/dev/null)"

# Get the LED settings from the JSON
json_get_var led_v "ledcolor"
json_get_var ledpat_v "ledpattern"

LED ${led_v} ${ledpat_v}

# This function will get called for each item in the 
# streams element of the JSON
function watch_match() {
    # Select the nested object by **index**
    json_select $2
    json_get_var port_v "port"
    json_get_var match_v "match"
    json_select ..
    
    # Run the command in the background
    MATCHSTREAM eth0 TCP ${port_v} "$match_v" &
}

# Use a command group to group all the streams
{
    json_for_each_item watch_match "streams"

    # Wait for any stream to trigger
    wait -n
    # Kill the other streams
    pkill -P $$
}

# We've matched a stream, send the device to jail
NETMODE JAIL

# Set the LED
LED R SOLID
```

There's a lot going on here!  Let's break it down:

1. We define a payload like usual, and set the network mode
2. We wait 10 seconds to get an IP because we want to use the network
3. We initialize the `jshn` library
4. We use the `wget` command to download our configuration payload
5. We extract some variables from the JSON payload and set the LED color
6. We define a function that gets called for each object in the `streams` element.
7. We use the second argument of the function, which is the index value, to descend into the nested object to obtain the port and match values.
8. We launch `MATCHSTREAM` in the background
9. We use a [command group](/packet-squirrel-mark-ii/advanced-payloads/command-groups.md) to run the `MATCHSTREAM` commands and wait for any of them to complete
10. The device is placed in `JAIL` mode and the payload exits.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.hak5.org/packet-squirrel-mark-ii/advanced-payloads/processing-json.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
