-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Will continue tomorrow * Will add descriptions tomorrow. * Will finish tomorrow morning first thing. * Will work on actual guide next. * Optimised images with calibre/image-actions * Update * Optimised images with calibre/image-actions * Ready for review. * Optimised images with calibre/image-actions --------- Co-authored-by: ninjeeter <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
528449a
commit cf57780
Showing
13 changed files
with
233 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Dealing with Binary Data | ||
|
||
Caido plugins are written in JavaScript. When creating a plugin that must handle raw bytes, there are some caveats to be aware of as the backend language used by Caido is Rust. | ||
|
||
## UTF-8 Encoding | ||
|
||
For Unicode code points outside of the ASCII range <span style="color: #EBEBF599; font-style: italic">(U+0000 to U+007F)</span> multiple bytes are used. | ||
|
||
When encoding code points into multibyte UTF-8 characters, the bytes are prefixed with specific bit patterns. The first byte prefix indicates how many bytes are used based on the number of leading '1's, and any subsequent <span style="color: #EBEBF599; font-style: italic">(continuation)</span> bytes begin with '10'. | ||
|
||
<img alt="UTF-8 encoding chart." src="/_images/utf_chart.png" center/> | ||
|
||
This can be an issue if you want to create a Caido plugin that sends invalid UTF-8 to a target server to see how it is processed. | ||
|
||
For example, if your intention is to append the byte `\x85` (`[1000 0101]`) to a path: | ||
|
||
1. JavaScript strings are encoded using UTF-16 (`[0000 0000 1000 0101]`). | ||
2. When passed to Rust, it is encoded as UTF-8. To produce valid UTF-8, the prefix is added to satisfy the multibyte pattern rules: | ||
- First byte `C2`: `[1100 0010]` <span style="color: #EBEBF599; font-style: italic">(prefix marks start of 2-byte sequence)</span> | ||
- Second byte `85`: `[1000 0101]` <span style="color: #EBEBF599; font-style: italic">(continuation byte)</span> | ||
3. Now, `[1100 0010 1000 0101]` is sent instead of the intended `[1000 0101]`. | ||
|
||
::: tip | ||
You can view this visually by listening for the request with Netcat: | ||
|
||
`ncat -lvnp 5555` | ||
|
||
<img alt="Unprintable character." src="/_images/replaced_character.png" center/> | ||
|
||
You can view the bytes by piping `xxd` to display the hex dump: | ||
|
||
`ncat -lvnp 5555 | xxd -g1` | ||
|
||
<img alt="C2 85" src="/_images/rust_conversion.png" center/> | ||
::: | ||
|
||
## Preserving the Raw Byte | ||
|
||
To avoid the conversion, the raw byte must be used instead. This can be accomplished by: | ||
|
||
1. Taking a request and returning a UInt8Array byte stream: | ||
|
||
`.getPath({raw: true})` | ||
|
||
2. Creating a new array that includes the existing bytes and the added byte: | ||
|
||
`let path = [...spec.getPath({raw: true}), 0x85]` | ||
|
||
3. Setting the path to use this new array: | ||
|
||
`spec.setPath(path)` | ||
|
||
::: tip | ||
Now, `C2` will not be prefixed: | ||
|
||
`ncat -lvnp 5555 | xxd -g1` | ||
|
||
<img alt="Just \x85." src="/_images/raw_byte_example.png" center/> | ||
::: | ||
|
||
## What's next? | ||
|
||
To view the full script and an additional technique that can be used to set raw bytes in Caido plugins, click [here](/guides/components/utf.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# Using Invalid UTF-8 | ||
|
||
::: tip | ||
For conceptual information regarding this guide - click [here](/concepts/backend/binary.md). | ||
::: | ||
|
||
## Using a Mutable Proxied Request | ||
|
||
To use invalid UTF-8 in the path of a request that passes through Caido, follow these steps: | ||
|
||
### /packages/backend/src/index.ts | ||
|
||
First import the `SDK`, the interface used to interact with Caido. | ||
|
||
``` ts | ||
import { SDK } from "caido:plugin"; | ||
``` | ||
|
||
Then create a function that takes proxied requests using `onInterceptRequest` and converts them into mutable, un-saved `RequestSpec` objects using the `.toSpec()` method. Next, store the path as a byte array using the spread operator `...`, and append the desired raw byte using `[...spec.getPath({raw: true}), 0x85];`. Update the request with the modified path using `.setPath()` and send the request. | ||
|
||
``` ts | ||
export function init(sdk: SDK) { | ||
sdk.events.onInterceptRequest(async (sdk, request) => { | ||
const spec = request.toSpec(); | ||
let path = [...spec.getPath({raw: true}), 0x85]; | ||
spec.setPath(path); | ||
await sdk.requests.send(spec); | ||
}); | ||
} | ||
``` | ||
|
||
## Using a Newly Created Request | ||
|
||
To use invalid UTF-8 in the path of a `new RequestSpecRaw()` request, follow these steps: | ||
|
||
### /packages/backend/src/index.ts | ||
|
||
First, import the required dependencies. `SDK` is the interface used to interact with Caido. `DefineAPI` is used to structure the API: definining what methods or endpoints are available, the parameters those methods accept and what types of values they return. `RequestSpecRaw` is an object class that is used to create a request in raw byte format. | ||
|
||
``` ts | ||
import { RequestSpecRaw } from "caido:utils"; | ||
import { SDK, DefineAPI } from "caido:plugin"; | ||
``` | ||
|
||
Next, define a function that will convert the path string into an array of bytes. | ||
|
||
``` ts | ||
function stringToUint8Array(str: string): Uint8Array { | ||
const arr = new Uint8Array(str.length); | ||
for (let i = 0; i < str.length; i++) { | ||
arr[i] = str.charCodeAt(i); | ||
} | ||
return arr; | ||
} | ||
``` | ||
|
||
Create an instance of the `RequestSpecRaw` class, by supplying the target URL as the constructor. | ||
|
||
``` ts | ||
async function testSendRequest(sdk: SDK): Promise<void> { | ||
console.log("Testing send request"); | ||
const req = new RequestSpecRaw("http://localhost:5555"); | ||
``` | ||
Call the `stringToUint8Array` function on the request data to convert it into a byte array. Send the request and if a response is received, print it in plaintext. | ||
``` ts | ||
const rawRequest = "GET /admin\x85 HTTP/1.1\r\nHost: localhost:5555\r\n\r\n"; | ||
req.setRaw(stringToUint8Array(rawRequest)); | ||
|
||
const res = await sdk.requests.send(req); | ||
console.log(res?.response.getRaw().toText()); | ||
} | ||
``` | ||
|
||
Since we are using a button on the frontend to issue this request, define the `testSendRequest` function as an API call and register it to the backend. | ||
|
||
``` ts | ||
export type API = DefineAPI<{ | ||
testSendRequest: typeof testSendRequest; | ||
}>; | ||
|
||
export function init(sdk: SDK<API>) { | ||
sdk.api.register("testSendRequest", testSendRequest); | ||
} | ||
``` | ||
|
||
::: tip | ||
<details> | ||
<summary>To view the entire frontend script, expand the following:</summary> | ||
|
||
``` ts | ||
import type { Caido } from "@caido/sdk-frontend"; | ||
import type { API } from "../../backend/src/index"; | ||
|
||
import "./styles/index.css"; | ||
|
||
export type CaidoSDK = Caido<API>; | ||
|
||
const Commands = { | ||
sending: "my-plugin-page.req", | ||
} as const; | ||
|
||
const sending = async (sdk: CaidoSDK) => { | ||
await sdk.backend.testSendRequest(); | ||
}; | ||
|
||
const createPage = (sdk: CaidoSDK) => { | ||
const requestButton = sdk.ui.button({ | ||
variant: "primary", | ||
label: "Send Request", | ||
}); | ||
|
||
requestButton.addEventListener("click", async () => { | ||
await sending(sdk); | ||
}); | ||
|
||
const bodyContainer = document.createElement("div"); | ||
bodyContainer.appendChild(requestButton); | ||
|
||
const card = sdk.ui.card({ | ||
body: bodyContainer, | ||
|
||
}); | ||
|
||
sdk.navigation.addPage("/my-plugin-page", { | ||
body: card, | ||
}); | ||
}; | ||
|
||
export const init = (sdk: CaidoSDK) => { | ||
createPage(sdk); | ||
sdk.sidebar.registerItem("My Plugin", "/my-plugin-page", { | ||
icon: "fas fa-rocket", | ||
}); | ||
|
||
sdk.commands.register(Commands.sending, { | ||
name: "Send Request", | ||
run: () => sending(sdk), | ||
}); | ||
}; | ||
``` | ||
|
||
</details> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters