AI 摘要(由 ChatGPT 总结生成):
本文介绍了一种使用 Bash 脚本模拟 HTTP 和 HTTPS 请求的方法,适用于缺少 wget 和 curl 命令的环境。文章提供了详细的脚本代码和使用方法,通过示例展示了脚本的效果和使用方法,包括如何处理 HTTP 和 HTTPS 协议。这种方法能够替代传统的 wget 和 curl 命令,实现网络请求的功能。
前言
之前写过一篇文章关于使用纯 Bash
模拟 HTTP
请求的文章,链接如下:
正好前阵子又分析了一个恶意挖矿脚本时遇到了一段相关代码,遂有感而发。
而且平时我们拿到一个 Shell
,进去后发现没有 wget
、curl
命令(特别是一些阉割较狠的 Docker
容器环境内),但是却具有完整的 Bash
环境,这时候我们可不可以使用 Bash
的特性,使得我们可以使用类似 wget
、curl
命令呢?这就是今晚水这篇文章的原因。废话不多说,直接上代码及食用教程。
代码
脚本代码比较粗糙,未做更好的优化,更多的是提供大家一个思路。
代码如下:
#!/bin/bash
_curl() {
local proto server path port
proto=$(echo "$1" | awk -F: '{print $1}')
server=$(echo "$1" | awk -F/ '{print $3}')
path=$(echo "$1" | awk -F/ '{for(i=4;i<=NF;i++) printf "%s", $i; print ""}')
local tag="close"
local ua="curl/7.29.0 (Shell)"
DOC="/${path}"
HOST="${server%%:*}"
PORT="${server##*:}"
if [[ "$proto" == "http" ]]; then
[[ "$PORT" == "$HOST" ]] && PORT=80
exec 3<>/dev/tcp/${HOST}/$PORT
FD_IN=3
elif [[ "$proto" == "https" ]]; then
[[ "$PORT" == "$HOST" ]] && PORT=443
# 对于 HTTPS 使用 coproc 创建子进程运行,避免脚本卡住
coproc openssl_process { openssl s_client -connect ${HOST}:${PORT} -quiet 2>/dev/null; }
exec 3>&${openssl_process[1]}
exec 4<&${openssl_process[0]}
FD_IN=4
else
echo "错误:不支持的协议。请使用 http 或 https。"
exit 1
fi
echo -en "GET ${DOC} HTTP/1.1\r\nHost: ${HOST}\r\nUser-Agent: ${ua}\r\nConnection: ${tag}\r\n\r\n" >&3
local chunked=false
while read -r line <&${FD_IN}; do
line="${line%%[[:cntrl:]]}"
[[ -z "$line" ]] && break
[[ "$line" =~ Transfer-Encoding:\ chunked ]] && chunked=true
done
if $chunked; then
_parse_chunked_body
else
cat <&${FD_IN}
fi
exec 3>&-
[[ "$proto" == "https" ]] && { exec 4<&-; wait $openssl_process_PID; }
}
_parse_chunked_body() {
while :; do
read -r chunk_size_hex <&${FD_IN}
chunk_size_hex="${chunk_size_hex%%[[:cntrl:]]}"
local chunk_size=$((16#$chunk_size_hex))
[[ $chunk_size -eq 0 ]] && break
dd bs=1 count=$chunk_size <&${FD_IN} 2>/dev/null
read -r _ <&${FD_IN}
done
}
if [[ -z "$1" ]]; then
echo "错误:未提供 URL 参数。"
echo "用法示例:$0 http(s)://example.com/path"
exit 1
else
_curl "$1"
fi
食用
可将上述代码保存到 Shell
脚本中或自行集成到自己的脚本中,食用方法如下(同步食用自带的 curl
命令模拟一遍做对照参考):
- HTTP 方式模拟如下:
[root@localhost tmpdir]# curl http://ip.isisy.com/8.8.8.8
IP: 8.8.8.8
AS: AS15169
City: Mountain View
Region: California
Country: US - United States(美国)
Timezone: America/Los_Angeles
Location: 37.4056,-122.0775
ISP: Google LLC
Scope: 8.8.8.8/32
Detail: 美国–加利福尼亚州–圣克拉拉–山景城谷歌公司DNS服务器
[root@localhost tmpdir]#
[root@localhost tmpdir]# ./_curl.sh http://ip.isisy.com/8.8.8.8
IP: 8.8.8.8
AS: AS15169
City: Mountain View
Region: California
Country: US - United States(美国)
Timezone: America/Los_Angeles
Location: 37.4056,-122.0775
ISP: Google LLC
Scope: 8.8.8.8/32
Detail: 美国–加利福尼亚州–圣克拉拉–山景城谷歌公司DNS服务器
[root@localhost tmpdir]#
- HTTPS 方式模拟如下:
[root@localhost tmpdir]# curl https://ip.isisy.com/robots.txt
User-Agent: *
Disallow: /
[root@localhost tmpdir]#
[root@localhost tmpdir]# ./_curl.sh https://ip.isisy.com/robots.txt
User-Agent: *
Disallow: /
[root@localhost tmpdir]#
可见请求结果基本一致,使用上述脚本时,还请使用完整的 HTTP(S)
链接,同时用户也可自己定义其请求端口,例如:
./_curl.sh http://example:8080/path
小结
本脚本基本实现了使用 Bash
的相关特性以请求网络地址,但还有较多待完善的地方,若其他大佬有兴趣可接着完善(或等我后续在慢慢完善~)。