欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

远程漏洞利用:无需借助套接字的Shellcode

来源:本站整理 作者:佚名 时间:2017-01-11 TAG: 我要投稿

在本文中,我将介绍一种优雅的技术,来获得一个shell访问易受攻击的远程机器。虽然这个技术不是我发明的,但我发现它的确很有趣,所以本文的重点是这种技术本身,而不是利用漏洞的具体方式。
设置环境
为了专注于远程shell代码本身,而不是把精力用在如何规避ASLR、非可执行堆栈等防御措施上面,我们将禁用这些安全功能。一旦熟悉了获取shellcode的方法,可以重新启用这些保护措施,以进一步练习如何突破这些安全设置。因此,这是一个非常有趣的练习,如果你想练手的话。
首先,我们将禁用ASLR。为此,可以使用以下命令:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
这些设置都是临时性质的,在下次重新启动时会全部还原。如果你想要在不重新启动机器的情况下立即还原所有设置的话,可以使用如下所示的命令:

echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
为了禁用其余的安全功能,我们可以使用以下选项来编译带有安全漏洞的服务器:

-fno-stack-protector -z execstack
这些选项会禁用堆栈的canarie保护,并赋予堆栈执行权限。这样的话,我们就得到了一个非常容易利用的环境。
带有安全漏洞的服务
现在,让我们编写一个带有缓冲区溢出漏洞的小型回显服务器,这样我们就可以远程利用它了。这个程序很简单,你能发现代码中的缓冲区溢出漏洞吗? 你当然可以。
#include
#include
 
#include
#include
#include
 
int
process_request (int s1, char *reply)
{
  char result[256];
 
  strcpy (result, reply);
  write (s1, result, strlen(result));
  printf ("Result: %p\n", &result);
  return 0;
}
 
int
main (int argc, char *argv[])
{
  struct sockaddr_in   server, client;
  socklen_t            len = sizeof (struct sockaddr_in);
  int                  s,s1, ops = 1;
  char                 reply[1024];
 
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_family = AF_INET;
  server.sin_port = htons(9000);
 
  s = socket (PF_INET, SOCK_STREAM, 0);
  if ((setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &ops, sizeof(ops)))
    perror ("pb_server (reuseaddr):");
  bind (s, (struct sockaddr *) &server, sizeof (server));
  listen (s, 10);
 
  while (1)
    {
      s1 = accept (s, (struct sockaddr *)&client, &len);
      printf ("Connection from %s\n", inet_ntoa (client.sin_addr));
      memset (reply, 0, 1024);
      read (s1, reply, 1024);
      process_request (s1, reply);
      close (s1);
    }
  return 0;
}
很好,下面我们就来编译它,让它变成一个最容易利用的服务器:

gcc -g -fno-stack-protector -z execstack -o target target.c
下面,我们来展示它的脆弱性。在一个终端运行这个带有安全漏洞的服务器,然后在另一个终端运行下列命令:

$ perl -e 'print "A"x1024;' | nc localhost 9000
在运行服务器的终端中,我们将会看到如下所示的内容:
$  ./target
Connection from 127.0.0.1
Result: 0x7fffffffdbf0
Segmentation fault (core dumped)
注意,我已经添加了打印局部变量的地址的语句,从而可以验证ASLR是否被禁用。每次执行这个二进制代码的时候,应该总是看到相同的数字(当然,如果你修改了这个程序,数字就会随之改变)。
现在,我们可以拿这个程序来练手,学习如何使用各种触手可及的shellcode来获取一个本地shell。尽管这个练习非常简单,但是我们建议您至少要练习一次。具体过程本文不作详细介绍,因为关于缓冲区溢出漏洞利用的教程,在网络上面数不胜数。
远程Shell
下面我们介绍如何获取远程shell。注意,这里的关键在于“远程”。这意味着在易受攻击的机器和攻击者之间,隔着一个网络。或者换句话说,我们必须通过一些套接字来发送/接收数据。根据这一要求,有两种方式可以用来获得远程shell:
如果你的shellcode创建一个服务器套接字来启用来自外部的连接请求,并从本地shell发送和接收数据 ...那么,这就是一个直接远程shell。
如果你的shellcode连接回一个预先指定的主机,并且这个主机上运行的服务器软件正在等待受害者的连接...那么,这就这是一个反向远程shell。
关于这两种远程shell的详细信息,请访问https://0x00sec.org/t/remote-shells-part-i/269。
看到这两个定义后,你可能会联想到RHOST/RPORT之类的变量....是的,它们可以用来告诉payload连接的主机地址和相应的端口。对于反向shell来说,您必须将这些信息存放到payload中,以便连接回来。对于直接shell你通常需要定义端口,服务器就会等待连接。
但是,至少对于Unix机器来说,还有第三种选择。
连接复用
当执行远程漏洞利用代码时,为了利用此漏洞,您已经连接到了服务器...所以,为什么不重用这个已经建立好的连接呢?这真是一个不错的想法,因为它不会显示任何会引起受害者怀疑的东西,例如来自服务器未知服务的开放端口等。
实现这一点的方法也非常巧妙。它是基于这样的事实,即系统是按顺序分配文件描述符的。知道了这一点,我们就可以在建立连接之后立即复制一个当前文件的描述符,除非服务器的负载很重,否则我们得到的文件描述符等于用于我们连接的套接字的文件描述符+1,这样很容易就能知道我们的连接的文件描述符了。

[1] [2] [3] [4]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载