You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/network-services-pentesting/pentesting-web/ruby-tricks.md
+78Lines changed: 78 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -92,9 +92,87 @@ Notes:
92
92
{{#endref}}
93
93
94
94
95
+
## Log Injection → RCE via Ruby `load` and `Pathname.cleanpath` smuggling
96
+
97
+
When an app (often a simple Rack/Sinatra/Rails endpoint) both:
98
+
- logs a user-controlled string verbatim, and
99
+
- later `load`s a file whose path is derived from that same string (after `Pathname#cleanpath`),
100
+
101
+
You can often achieve remote code execution by poisoning the log and then coercing the app to `load` the log file. Key primitives:
102
+
103
+
- Ruby `load` evaluates the target file content as Ruby regardless of file extension. Any readable text file whose contents parse as Ruby will be executed.
104
+
-`Pathname#cleanpath` collapses `.` and `..` segments without hitting the filesystem, enabling path smuggling: attacker-controlled junk can be prepended for logging while the cleaned path still resolves to the intended file to execute (e.g., `../logs/error.log`).
105
+
106
+
### Minimal vulnerable pattern
107
+
108
+
```ruby
109
+
require'logger'
110
+
require'pathname'
111
+
112
+
logger =Logger.new('logs/error.log')
113
+
param =CGI.unescape(params[:script])
114
+
path_obj =Pathname.new(param)
115
+
116
+
logger.info("Running backup script #{param}") # Raw log of user input
117
+
load"scripts/#{path_obj.cleanpath}"# Executes file after cleanpath
118
+
```
119
+
120
+
### Why the log can contain valid Ruby
121
+
`Logger` writes prefix lines like:
122
+
```
123
+
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
124
+
```
125
+
In Ruby, `#` starts a comment and `9/2/2025` is just arithmetic. To inject valid Ruby code you need to:
126
+
- Begin your payload on a new line so it is not commented out by the `#` in the INFO line; send a leading newline (`\n` or `%0A`).
127
+
- Close the dangling `[` introduced by the INFO line. A common trick is to start with `]` and optionally make the parser happy with `][0]=1`.
128
+
- Then place arbitrary Ruby (e.g., `system(...)`).
129
+
130
+
Example of what will end up in the log after one request with a crafted param:
131
+
```
132
+
I, [9/2/2025 #209384] INFO -- : Running backup script
Copy file name to clipboardExpand all lines: src/pentesting-web/race-condition.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -223,6 +223,14 @@ while "objetivo" not in response.text:
223
223
response = requests.get(url, verify=False)
224
224
```
225
225
226
+
#### Turbo Intruder: engine and gating notes
227
+
228
+
- Engine selection: use `Engine.BURP2` on HTTP/2 targets to trigger the single‑packet attack; fall back to `Engine.THREADED` or `Engine.BURP` for HTTP/1.1 last‑byte sync.
229
+
-`gate`/`openGate`: queue many copies with `gate='race1'` (or per‑attempt gates), which withholds the tail of each request; `openGate('race1')` flushes all tails together so they arrive nearly simultaneously.
230
+
- Diagnostics: negative timestamps in Turbo Intruder indicate the server responded before the request was fully sent, proving overlap. This is expected in true races.
231
+
- Connection warming: send a ping or a few harmless requests first to stabilise timings; optionally disable `TCP_NODELAY` to encourage batching of the final frames.
232
+
233
+
226
234
### Improving Single Packet Attack
227
235
228
236
In the original research it's explained that this attack has a limit of 1,500 bytes. However, in [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), it was explained how it's possible to extend the 1,500-byte limitation of the single packet attack to the **65,535 B window limitation of TCP by using IP layer fragmentation** (splitting a single packet into multiple IP packets) and sending them in different order, allowed to prevent reassembling the packet until all the fragments reached the server. This technique allowed the researcher to send 10,000 requests in about 166ms.
0 commit comments