我正在处理一个大型的private / 8网络,需要枚举所有正在侦听端口443并在HTTP HEADER响应中声明的特定版本的Web服务器.
首先,我考虑使用连接扫描运行nmap,并通过输出文件grep自己,但结果抛出许多误报,其中nmap声明端口被“过滤”而实际上它是“打开”(使用连接扫描: nmap -sT -sV -Pn -n -oA foo 10.0.0.0/8 -p 443).
所以现在我想用bash和curl编写脚本 – 伪代码就像:
for each IP in 10.0.0.0/8 do: curl --head https://{IP}:443 | grep -iE "(Server\:\ Target)" > {IP}_info.txt; done
由于我不熟悉bash,我不确定如何正确编写脚本 – 我必须:
>循环遍历所有IP
>确保只有X威胁并行运行
>理想情况下,将输出切换为仅在一个文件中记下匹配主机的IP
>理想情况下,确保仅记下匹配的服务器版本
任何建议或指向一个方向是高度赞赏.
解决方法
小规模 – 迭代
对于较小的IP地址范围,可能建议迭代如下:
for ip in 192.168.1.{1..10}; do ...
如similar question所述.
大规模 – 平行!
鉴于您的问题涉及巨大的IP地址范围,您应该考虑采用不同的方法.
这就要求使用gnu parallel.
使用gnu parallel在bash中并行迭代大量IP地址需要将逻辑拆分为多个文件(对于要使用的并行命令).
ip2int
#!/bin/bash set -e function ip_to_int() { local IP="$1" local A=$(echo $IP | cut -d. -f1) local B=$(echo $IP | cut -d. -f2) local C=$(echo $IP | cut -d. -f3) local D=$(echo $IP | cut -d. -f4) local INT INT=$(expr 256 "*" 256 "*" 256 "*" $A) INT=$(expr 256 "*" 256 "*" $B + $INT) INT=$(expr 256 "*" $C + $INT) INT=$(expr $D + $INT) echo $INT } function int_to_ip() { local INT="$1" local D=$(expr $INT % 256) local C=$(expr '(' $INT - $D ')' / 256 % 256) local B=$(expr '(' $INT - $C - $D ')' / 65536 % 256) local A=$(expr '(' $INT - $B - $C - $D ')' / 16777216 % 256) echo "$A.$B.$C.$D" }
scan_ip
#!/bin/bash set -e source ip2int if [[ $# -ne 1 ]]; then echo "Usage: $(basename "$0") ip_address_number" exit 1 fi CONNECT_TIMEOUT=2 # in seconds IP_ADDRESS="$(int_to_ip ${1})" set +e data=$(curl --head -vs -m ${CONNECT_TIMEOUT} https://${IP_ADDRESS}:443 2>&1) exit_code="$?" data=$(echo -e "${data}" | grep "Server: ") # wasn't sure what are you looking for in your servers set -e if [[ ${exit_code} -eq 0 ]]; then if [[ -n "${data}" ]]; then echo "${IP_ADDRESS} - ${data}" else echo "${IP_ADDRESS} - Got empty data for server!" fi else echo "${IP_ADDRESS} - no server." fi
scan_range
#!/bin/bash set -e source ip2int START_ADDRESS="10.0.0.0" NUM_OF_ADDRESSES="16777216" # 256 * 256 * 256 start_address_num=$(ip_to_int ${START_ADDRESS}) end_address_num=$(( start_address_num + NUM_OF_ADDRESSES )) seq ${start_address_num} ${end_address_num} | parallel -P0 ./scan_ip # This parallel call does the same as this: # # for ip_num in $(seq ${start_address_num} ${end_address_num}); do # ./scan_ip ${ip_num} # done # # only a LOT faster!
迭代方法的改进:
The run time of the naive for loop (which is estimated to take 200 days for 256*256*256 addresses) was improved to under a day according to @skrskrskr.