Funny characters returned from read function of Net_SSH2 library (phpseclib) - phpseclib

When I use the Net_SSH2 library and the read/write functions like this:
$ssh = new Net_SSH2($strServerIPAddress);
if(!$ssh->login($strServerUsername, $strServerPassword))
die("error");
$ssh->write(" service httpd reload\n");
$strApacheRestartResult = $ssh->read("[root#$strServerName ~]#");
$ssh->disconnect();
I get funny characters in the read function results ($strApacheRestartResult) that I dont see when running the same thing via Putty, see below:
service httpd reload
Reloading httpd: [60G[[0;31mFAILED[0;39m]
[root#server1 ~]#
Why are these [60G[[0;31m and [0;39m] in the return data from the read function?

They're ANSI control codes. Their purpose is to control the formatting of the text and the color and what not. To decode them properly you'd need a terminal emulator. phpseclib has one called File_ANSI:
http://phpseclib.sourceforge.net/ssh/examples.html#top
Here's your code rewritten to use it:
$ssh = new Net_SSH2($strServerIPAddress);
$ansi = new File_ANSI();
if(!$ssh->login($strServerUsername, $strServerPassword))
die("error");
$ssh->write(" service httpd reload\n");
$ansi->appendString($ssh->read("[root#$strServerName ~]#"));
echo $ansi->getScreen();
$ssh->disconnect();

Related

Pass Kerberos keytab from StringIO to kinit

I am writing a small Python utility that stores a Kerberos v5 keytab in a StringIO object. I want to avoid storing said keytab anywhere on the machine's disk.
Therefore, I would very much want to invoke kinit like this (split() and subprocess() to follow):
command = "/usr/bin/kinit -V -c {0} -t {1} {2}#{3}".format(cache, ticket, loginUser, kerberosDomain)
where the ticket is:
ticket = StringIO.StringIO(data)
But kinit doesn't really like it. Its source file says:
925 /* Ensure we can be driven from a pipe */
Does anyone have experience with driving kinit from a pipe, and specifically how to inject the ticket into (presumably) its stdin?
Alternatively, can a StringIO be wrapped into something like mmap to behave like a "real" file to kinit?
Thanks!
PS: A very interesting discussion I read as I was posting this question:
Python - How do I pass a string into subprocess.Popen (using the stdin argument)?

ssh remote login to server using system(char * command), and excute commands?

Someone familiar with SSH and System(const char * command) to execute shell command!??
Am trying to remotely login to multiple servers/machines from my C++ code, and i have to execute some commands remotely. To the best of my experience, i decided to use ssh. But, now i want to load and send all my commands through the System(const char * command). pls see my code below..
#include "all my headers"
int main()
{
system("ssh 172.10.10.1");//login to server_one, password=123
system("ssh 172.10.10.2");//login to server_two, password=1234
system("ssh 172.10.10.3");//login to server_three,password=12345
system("ssh 172.10.10.4");//login to server_four, password=123456
return 0;
}
Now,my Question is:
can i load and send the remote_ip of the servers and password at the
same time, something like: system("ssh 172.10.10.4 ,123456")
password=123456? if yes, how?
if am done with (1) above, i will have another question. thanks.
Calling system("ssh ...") will ONLY work if you have set up public keys for the machine you want to log in on.
The reason is that the system() does not allow you to interact with the process you started, it will just spawn a new shell and pass the relevant string to the shell for execution, and ssh does not itself have a way to pass the password to the application, you have to actually type it in (or send it to the stdin side of ssh if you use popen - but I would really suggest that public keys are the right way to go in an automated system).
If you still need to interact with the created process, you will need to use something like popen, which will allow you to read stdout or write to stdin on the - or even pipe() and fork() if you need the ability to do stuff to both stdin and stdout.

Permissions issue calling bash script from c++ code that apache is running

The goal of this code is to create a stack trace whenever a sigterm/sigint/sigsegv/etc is caught. In order to not rely on memory management inside of the C++ code in the case of a sigsegv, I have decided to write a bash script that will receive the PID and memory addresses in the trace array.
The Sig events are being caught.
Below is where I generate the call to the bash script
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Below is where my issue arises. The command in syscom is generating correctly. I can stop the code before the following popen, run the command in a terminal, and it functions correctly.
However running the script directly from the c++ code does not seem to work.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
The purpose of the bash script is to get the offset from /proc/pid/maps, and then use that to run addr2line to get the file name/line number.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
However offset is getting 0 when I run from the c++ code, but when I run the exact same command (that is stored in syscom in the c++ code) in a terminal, I get the expected output.
I have been trying to fix this for a while. Permissions are most likely the issue, but I've tried to work around these with every way I know of/have seen via google. The user trying to run the script (currently running the c++ code) is apache.
The fix does not need to worry about the security of the box. If something as simple as "chmod 777 /proc -r" worked, that would have been the solution (sadly the OS doesn't let me mess do such commands with /proc).
Things I've already tried:
Adding `` around the command that's stored in syscom from the c++ code
chown the script to apache
chmod 4755 on the bash_crash_supp.sh script, allowing it to always fire as root.
I have added apache to sudoers (visudo), allowing them to run sudo without using a password
I have added a sub file to sudoers.d (just in case) that does the same as above
I have looked into objdump, however it does not give me either the offset or the file/line num for an addr (from what I can see)
I have setuid(0) in the c++ code to set the current user to root
Command generated in C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Can anyone think of any other ways to solve this?
Long story short, almost all Unix-based systems ignore setuid on any interpreted script (anything with a shebang #!) as a security precaution.
You may use setuid on actual executables, but not the shell scripts themselves. If you're willing to take a massive security risk, you can make a wrapper executable to run the shell script and give the executable setuid.
For more information, see this question on the Unix StackExchange: https://unix.stackexchange.com/a/2910

zmq ventilator/worker/sink paradigm not working w/ subprocess

I am trying to replicate the ventilator/workers/sink paradigm described in the ZMQ guide. I have the same Python Ventilator, the same C++ worker as, and the same Python Sink as was described in the ZMQ examples. I want to launch the ventilator, workers, and sink from one main python script, so I created "class" wrappers around the ventilator & sink, and both of those classes subclass the Python module "multiprocessing.Process." Since the C++ is a binary, I launch it with Python's subprocess.Popen call.
The order of starting all of this up is as follows:
h = subprocess.Popen('test') # test is the name of the binary
time.sleep(1)
s = sinkObj.start()
time.sleep(1)
v = ventObj.start()
What I am finding is that no data is getting through the system when I start up the components like this. However, if I start the C++ binary in its own shell, and only start the sinkObj and ventObj from the main python script, it works fine.
I apologize in advance if this is more of a Python question than a ZMQ question, but I haven't run into issues like this w/ Python's subprocess. I have also tried using os.system() instead of the subprocess... but same issue. I put all the code on this website: https://github.com/kkarrancsu/zmqtest if anybody is curious to test it out. There is a readme on that git which tells you what the files are.
Any ideas on why this could be happening?
------------------------- UPDATE --------------------
I found that if I create a shell script which simply launches the C binary, and call that shell script w/ os.system('run_the_shell_script') it works! So this means that there is something wrong with the way that I am using subprocess.Popen(...), but can't seem to pinpoint what the issue is. I tried w/ the shell=True flag, but it still hangs with that...
It's the name of the worker binary file that causes the problem.
There two solutions:
Chang the name of the binary file test to test_new and do the same in your All.py file, and then it will work as you desire.
Substitute subprocess.Popen('./test', shell=True) for subprocess.Popen('test', shell=True).
test is Linux command. If you type the following in your shell
$ echo $PATH
You may see that . is at the last position. It means that until shell couldn't find the binary file to be executed in the directories that $PATH indicates, it will try to search for it in the current directory .
When you execute subprocess.Popen('test', shell=True), it could find it before trying the . directory and so it won't execute the workers.
As I see, the ventilator and sink bind() to ports 6557 and 6558, and the C++ app connect() to these ports. In this case, if you start the cpp app first, it will try to connect() to the endpoints, but as nothing is bound there, it will drop silently.
In ZeroMQ the basic principle is "First Bind, then Connect". So you should not connect() before you bind() something on the socket. Imagine bind() is the 'Server', and connect() is the client. You cannot connect client to non-existing server. Also, in ZeroMQ every socket can be 'Server', but you SHOULD HAVE only 1 bind()-ing socket per URL. And you can have multiple 'connect()'s.

Mkdir over SSH with Python does not work

I'm trying to create a new dir via SSH with a python script. When i try my commands by using the Python command line it just works. But when I try to do the same by a script it does not create the new 'test' folder (I even copy/paste the commands in the script into the Python cmd to verify they are right and there they work). So any ideas why it does not work by script?
The used code:
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect=('password:')
child.sendline('MyPwd')
child.sendline('mkdir /home/myUser/Desktop/test')
Seems to work when I just add another line
for example
child.sendline('\n')
so the entire script is
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect=('password:')
child.sendline('MyPwd')
child.sendline('mkdir /home/myUser/Desktop/test')
child.sendline('\n')
What I usually do to solve this issue is sync-ing with host machine. After I send something to the machine, I expect an answer, which usually translates in the machine's prompt. So, in your case, I would go for something like this:
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect('password:')
child.sendline('MyPwd')
child.expect('YourPromptHere')
child.sendline('mkdir /home/myUser/Desktop/test')
child.expect('YourPromptHere')
You can just replace YourPromptHere with the prompt of the machine, if you are running the script on a single target, or with a regular expression (eg. "(\$ )|(# )|(> )").
tl;dr : To summarize what I said, you need to wait until the previous action was finished until sending a new one.