113

So let's say one typoed something in their .bashrc that prevents him (or her) from logging in via ssh (i.e. the ssh login exits because of the error in the file). Is there any way that person could login without executing it (or .bashrc since the one runs the other), or otherwise delete/rename/invalidate the file?

Suppose you don't have physical access to the machine, and this is the only user account with the ability to ssh in.

For Reference: .bash_profile includes .bashrc:

[[ -f ~/.bashrc ]] && . ~/.bashrc

Edit: Things I have tried:

ssh user@host "rm ~/.bashrc"

scp nothing user@host:/RAID/home/tom/.bashrc

ssh user@host  "/bin/bash --norc"

All give the error:

/RAID/home/tom/.bashrc: line 16: /usr/local/bin/file: No such file or directory
/RAID/home/tom/.bashrc: line 16: exec: /usr/local/bin/file: cannot execute: No such file or directory
1
  • 5
    Your scp command will not work because scp will also read .bashrc when connecting. To avoid the problem In the future, you may add something like [ -z "$PS1" ] && return at the beginning of ./bashrc. This way scp will stop parsing .bashrc after the first line, and you will be able to overwrite it in case of emergency.
    – dalloliogm
    Aug 26, 2016 at 9:27

21 Answers 21

31

I think your only options are:

  • ssh in as another user and su to your account;

  • use something like ftp or smbclient, if the relevant services are enabled on the host;

  • find an open vulnerability in an open network service and exploit it :).

  • get an admin to fix the problem.

4
  • 8
    "Suppose you don't have physical access to the machine, and this is the only user account with the ability to ssh in." Dec 15, 2009 at 16:05
  • I am going down this route. I will post the solution after I find it. Fortunetly, I have a few avenues of attack.
    – Tom Ritter
    Dec 15, 2009 at 21:07
  • 6
    used Filezilla to SFTP into my server and it fixed me. Thanks soooo much, you saved me. I had a "exit 1" condition in my .bash_profile by accident and it hosed me.
    – djangofan
    Oct 19, 2012 at 23:46
  • Am I correct in assuming the network service you exploit would need to be one with the necessary permissions to modify the problematic .bashrc file?
    – Sparkette
    Oct 20, 2022 at 4:19
176

ssh -t username@hostname /bin/sh works for me.

9
  • 1
    Trying to do this with the Secure Shell app in Google Chrome (chrome.google.com/webstore/detail/secure-shell/…) but can't figure out how/where to put the command line arguments. Any tips?
    – Benj
    Feb 19, 2014 at 14:19
  • 2
    This doesn't work for me (though it should according to the man page). The local host runs ubuntu 14.04.1 and it's ubuntu 12.04.5 on the remote host. I'm unable to rsync because my login shell is tcsh and on the remote host it prints garbage (tcsh: No such file or directory tcsh: Trying to start from "/u/levy" -- which I'm told it's because the directory is NSF mounted). I thought I'd solve the problem bypassing the login shell but that doesn't work. Mar 28, 2015 at 3:00
  • 3
    If your default shell is csh/tcsh it will always source your .cshrc/.tcshrc even for non-interactive shells. Jul 17, 2015 at 21:37
  • 2
    I'm sitting here laughing my ass off at my own stupidity to have gotten to this point. Your solution worked great. Thank you so much for helping this tinkerer get some work done Jan 28, 2017 at 4:54
  • 2
    @Tom Ritter - this needs to be the accepted answer. Jun 11, 2020 at 20:45
68

I've had the same problem, and somehow was able to solve it. I used ssh to access the system, and pressed and held Ctrl+c as soon as I logged into the system. Then, ~/.bashrc was not read, and I was able to modify it.

9
  • 19
    I was skeptic, but this actually works...
    – rmobis
    May 19, 2016 at 19:42
  • 3
    This is genius! Nov 11, 2016 at 11:14
  • Actually works...thanks! The other methods never worked for me. Oct 30, 2017 at 0:25
  • on mac with only a .bash_profile, this worked for me :) Jan 13, 2018 at 14:51
  • 3
    Yes! This is the only one that works for me
    – DavidC
    Aug 19, 2019 at 10:05
40

You need to a) start bash without source'ing either ~/.bashrc or ~/.bash_profile and b) since such a shell wouldn't be a full login shell / have no tty attached, force ssh to attach a tty:

ssh -t user@host bash --norc --noprofile
3
  • 5
    This works, but note that you won't have your usual prompt, just an empty screen. try doing an ls to convince yourself that you're in :). Also note this will use a dumb term, so for me nano doesn't work Sep 4, 2018 at 8:22
  • 1
    @CiprianTomoiagă well that's kind of the idea, since the premise of the question is that .bashrc is busted :) This should get you far enough to be able to clean up the damage, then you can try to ssh again into a normal shell.
    – dimo414
    Mar 18, 2020 at 7:58
  • indeed ! I was just a bit confused at first as there wasn't even a $ symbol to indicate the prompt :). Mar 18, 2020 at 11:16
23

I used a published CVE to execute a command as root through a web interface in a network monitoring software I had installed. rm /RAID/home/tom/.bashrc

Then I could login and svn revert the changes I made.

4
  • 13
    That is both awesome and failriffic at the same time.
    – MikeyB
    Feb 18, 2011 at 22:18
  • 1
    @TomRitter : Please provide that ᴄᴠᴇ reference. Oct 16, 2015 at 13:24
  • 2
    It was in an oooold version of cacti, so unless you're running 8-year old software I don't think it will help you. And if you are running 8 year old software, I can't help you. ;)
    – Tom Ritter
    Oct 16, 2015 at 20:32
  • Surprisingly worked for me. Thanks. Mar 5, 2020 at 23:38
8

You're out of luck.

All ssh commands run your login shell. ssh $COMMAND runs $SHELL -c $COMMAND, scp runs $SHELL -c /path/to/sftp-server, plain ssh just runs your shell.

4
  • 3
    This is also true for sftp - even SSH subsystems are apparently executed from within a shell.
    – lxgr
    Jun 9, 2014 at 23:17
  • In my experience you are correct, even though the ssh man page says "If command is specified, it is executed on the remote host instead of a login shell." Yet the poster was able to solve the problem using the highest-rated answer (ssh hostname /bin/sh). What gives? Mar 26, 2015 at 21:15
  • @Silvio, OP's answer is that he used an exploit not related to SSH.
    – Tobu
    Mar 27, 2015 at 23:48
  • Right. Someone reported success with the highest-rated answer and I hastily assumed it was the OP. I wish it did work -- I have a similar situation, though it's merely annoying not crippling. (See my comment under the highest-rated answer above.) Mar 28, 2015 at 3:02
6

None of the above answers can bypass the login shell of ssh. You can pass a full command line, and so it runs the remote shell to process the command and set the working environment for the command. That's what shells are for and it's the Unix way. You would have all sorts of compatibility problems if you tried to run something without a shell. Likewise, trying a control-C should do the same as calling exit which is the behavior you are trying to avoid. If bash continues its a bug. Why people keep saying that the man page says something different need to quote it because it says nothing of the sort in my man page.

Additionally, on most linux systems, specifying /bin/sh does NOTHING since this is just a symlink to bash!

Wanna test? Add "echo" statements to you .bashrc and .profile and see which is run. I did. Here's the results.

ssh user@host will execute .bash_profile ssh user@host /bin/bash will execute .bashrc, but it thinks its non-interactive (no prompt). ssh -t user@host /bin/bash executes .bashrc twice ... once at login, once for the passed command, so specifying ANY shell will always run the first. ssh -T user@host is the same as not specifying -T or -t at all.

Now, if you notice, MY system isn't running both files, only one or the other. But the original poster has a line in .bash_profile running .bashrc, so .bashrc will always get run no matter what. Shouldn't have put that line there! If that line didn't exist, you wouldn't have had a problem.

You'll need to find another way in or find an admin. This is what admins are for.

1
  • Some good points; no executable passed as a command can help, as you explain, but on a somewhat moot point: if /bin/sh did get to execute first, it would help, because Bash doesn't load ~/.bashrc when invoked as sh. This answer is a superset of your other answer, so please delete the other one.
    – mklement
    Mar 29, 2017 at 21:23
4

Something like:

ssh host "/bin/bash --norc"

which seems to work, but note that PS1 is not set so you'll be typing commands without a prompt.

This has the advantage of being non-destructive.

5
  • 1
    This doesn't work, it tried for a successful login first, but can't login, and therefore can't run bash --norc
    – Tom Ritter
    Dec 15, 2009 at 12:27
  • I still have PS1 set when running with --norc. Feb 12 at 20:39
  • @MichaelMior: PS1 gets a default value. From man bash: "The default value is ''\s-\v\$ ''". Feb 13 at 18:17
  • @DennisWilliamson That was my point. You don't end up "without a prompt." Feb 15 at 2:12
  • @MichaelMior: I just now (again) tried the command in my answer and I don't get a prompt. My comment above was premature. Feb 15 at 13:59
3
ssh -t user@host "bash --norc --noprofile -c '/bin/rm .bashrc'"
1
  • This worked for me in a very restricted environment when nothing would. I had to specify the full path to .bashrc.
    – zbeekman
    May 23, 2018 at 15:28
2

try

echo ^C | ssh <hostname> ' rm .bashrc'

^C there is control-v then c

1
  • 2
    It's ctrl-v and ctrl-c on my system. Thanks anyway! :)
    – mzuther
    Feb 14, 2016 at 13:24
1

Mashing ctrl-C works as long as you can get a ctrl-C in before the .bashrc exits. Unfortunately, this can be difficult to do if exit is early in the .bashrc.

You can put in a ctrl-C as soon as possible by piping it to ssh directly:

{ echo ^C; cat /dev/tty; } | ssh -tt user@host

Note that ^C is typed like ctrl-V followed by ctrl-C.

This pipes a single ctrl-C followed by input from the controlling terminal, while -tt forces a psuedo-terminal to be allocated. All told this gives you a (somewhat malformed) shell on the remote machine while bypassing as much of .bashrc as is possible.

0

You can try to overwrite the .bash_profile with an empty file using the scp command. From what I have googled, scp use a non-interactive login that does not read .bash_profile.

3
  • Unless I'm (hypothetically) remembering the directory structure wrong, and it's not giving me an error on that, this does not work - scp also runs the file(s).
    – Tom Ritter
    Dec 15, 2009 at 12:30
  • 1
    The thing that people are not realizing is that scp isn't anything special; it's just another command run over ssh -- which means just about everything that happens for an interactive ssh session happpens with scp, also.
    – larsks
    Dec 15, 2009 at 14:24
  • what about sftp, afaik its a ssh subsystem.
    – allo
    Mar 16, 2017 at 23:42
0

You can also just delete the bashrc file:

ssh <hostname> rm ~/.bashrc
2
  • The problem is in the .bash_profile file, not in the bashrc. Dec 15, 2009 at 12:31
  • 1
    This doesn't work - it tries for a shell first and fails.
    – Tom Ritter
    Dec 15, 2009 at 12:32
0

If you system is setup normally, .bash_profile won't be run for a non-interactive shell (such as running a command).

Since you state the problem is in the .bash_profile file, try moving it out of the way:

ssh user@host "mv ~/.bash_profile ~/.bash_profile_broken"
2
  • I didn't think which way the files were linked mattered - .bash_profile includes .bashrc =( I added more info.
    – Tom Ritter
    Dec 15, 2009 at 12:37
  • 1
    But what Lockie is suggesting -- which is confirmed by the bash man page -- is that a non-interactive shell will not run either .bashrc or .bash_profile. However, even when you pass commands on the ssh command line (like in this example), bash is still started as an "interactive" shell, which means it will read your .bashrc file. So a good idea, but unfortunately ssh won't cooperate.
    – larsks
    Dec 15, 2009 at 14:32
0

UH='user@host'; ssh $UH 'mv ~/.bashrc ~/letmein'; ssh $UH

Please don't cut and run, change user and host, then edit letmein and save as .bashrc

0

Kudos to user60069, it worked for me, but I use the shell-specific startup file .bashrc, so logging in with /bin/sh worked for me.

However, if you are in the "no such luck" situation, I offer this solution, based on user60069's and Dennis W's solutions:

ssh -t you@host  /bin/bash --noprofile  --norc

Dennis W offered the --norc option, which someone said did not work for them.

Run "man bash" or "man (your shell)" for options to disable the start up files. You only need to use an abhorrent shell for the time it takes to fix the problem.

0

Other way to login to server is without profile, please find below command
ssh -t user@host bash --noprofile

For AWS using pem file and no other user
ssh -ti "YOUR-PEM-FILE-NAME.pem" ec2-user@YOUR-IP-ADDRESS bash --noprofile

Hope this helps!

0

That's works for me

$ ssh <hostname> bash --rcfile /dev/null
0

Simply move the old .bashrc out of the way:

ssh user@wherever mv /home/ubuntu/.bashrc /home/ubuntu/.bashrc_old

Now ssh in normally :)

(since you don't run .bashrc when running commands; this worked great for me :) )

1
  • Exactly this solution has already been posted 12 years ago. Oct 28, 2021 at 19:28
0

I think you can modified /etc/passwd file.

for example for

user:x:1015:1015::/home/user

So you hasnt access to bash

-1

From the suggestions and responses given above, I'd say it's not the .bashrc or .bash_profile files. Also ssh manpage says that if you specify a command to be executed then your profile files won't be read.

I'd suggest try executing a different login shell (ksh? csh? sh?) from the absolute path; also, beware that it might be a totally different problem (quota? execute and read permission on your home directory?), so a side approach would be better. Can you ask another user to do a ls -la $YOUR_HOME_DIR and mail you the result?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .