侦察脚本编写(正则+getopts)2

admin 2024年6月20日13:36:10评论14 views字数 8335阅读27分47秒阅读模式
本文由uuwan翻译《Bug Bounty Bootcamp The Guide to Finding and Reporting Web Vulnerabilities》 by Vickie Li,如果侵权还请及时联系。

      请点击文末#Bug Bounty Bootcamp标签查看合集或关注公众号点击底部【漏洞书籍】子菜单,如果对您有帮助还请点赞、在看、评论、转发、关注、打赏哦,您的互动就是我更新最大的动力!

  • 分析结果

现在我们有了一个工具,它可以执行三种类型的扫描,并将结果存储到文件中。但在扫描之后,我们仍然需要手动读取并理解复杂的输出文件。有没有办法加快这一过程?
假设您想在输出文件中搜索某条信息。您可以使用全局正则表达式打印(grep)来实现这一点。此命令是用于在文本、文件和命令输出中执行搜索的实用命令。一个简单的grep命令如下所示:
grep password file.txt
这告诉grep在文件file.txt中搜索字符串password,然后在标准输出中打印匹配的行。
例如,我们可以快速搜索Nmap输出文件,看看目标是否打开了80端口:
$ grep 80 TARGET_DIRECTORY/nmap80/tcp open http
您还可以通过在搜索字符串中使用正则表达式来使搜索更加灵活。正则表达式是一个特殊的字符串它描述了一个搜索模式。它可以帮助您只显示输出的特定部分。例如,您可能已经注意到Nmap命令的输出如下所示:

侦察脚本编写(正则+getopts)2

您可能想要从文件中删除不相关的消息,使它看起来更像这样:

侦察脚本编写(正则+getopts)2

使用此命令可过滤掉Nmap输出的开始和结束处的消息,并只保留报告的基本部分:
grep -E "^S+s+S+s+S+$" DIRECTORY/nmap > DIRECTORY/nmap_cleaned
-E标志告诉grep你使用的是正则表达式。正则表达式由两部分组成:常量和运算符。常量是字符串,而运算符是对这些字符串操作的符号。
  • 正则表达式

这两个元素一起使正则表达式成为模式匹配的强大工具。下面是对正则表达式运算符的快速概述:
d    匹配任何数字digitalw    匹配任何字符words    匹配任何空白spaceS    并匹配任何非空白.     与任何单个字符相匹配   转义了一个特殊的字符^    与字符串或行的开头相匹配$    匹配字符串或行的末尾
一些操作符还指定了要匹配的字符数
*        与前面字符匹配零或多次+        匹配前一个字符一个或多次{3}      匹配前面的字符三次{1,3}    匹配前面的字符一到三次{1、}    匹配前面的字符一次或多次[abc]    匹配方括号内的其中一个字符[a-z]    匹配a-z范围内的其中一个字符(a|b|c)  匹配a或b或c
让我们再看一遍我们的正则表达式。还记得s如何匹配任何空白,以及s如何匹配任何非空白吗?
这意味着s+将匹配任何空白一个或多个字符长,而s+将匹配任何非空白的一个或多个字符长
这个正则表达式指定了我们应该提取被2个空白分隔的3个字符串的行:
"^S+s+S+s+S+$"

过滤后的输出结果如下:

侦察脚本编写(正则+getopts)2

为了考虑到命令输出中可能存在的额外空格,让我们在搜索字符串周围再添加两个可选空格:
"^s*S+s+S+s+S+s*$"
您可以使用许多更高级的正则表达式特性来执行更复杂的匹配。然而,这组简单的操作符可以很好地满足我们的目的。要获得正则表达式语法的完整指南,请阅读参考手册
https://www.rexegg.com/regex-quickstart.html
  • 构建主报告

  • 解析json数据+添加日期

如果您想从三个输出文件中生成一个主报告,该怎么办?您需要从crt.sh中解析JSON文件。您可以使用jq,一个处理JSON的命令行实用程序来实现这一点。
如果我们检查crt.sh输出的JSON文件,可以看到我们需要提取每个证书项的name_value字段来提取域名。
https://crt.sh/?q=google.com&output=json
[  {    "issuer_ca_id": 12254,    "issuer_name": "C=NL, O=DigiNotar, CN=DigiNotar Public CA 2025, [email protected]",    "common_name": "*.google.com",    "name_value": "[email protected]*.google.com",    "id": 3144337544,    "entry_timestamp": "2020-07-26T13:26:21.356",    "not_before": "2011-07-10T19:06:30",    "not_after": "2013-07-09T19:06:30",    "serial_number": "05e2e6a4cd09ea54d665b075fe22a256",    "result_count": 2  },  {    "issuer_ca_id": 4,    "issuer_name": "C=US, O=Google Inc, CN=Google Internet Authority",    "common_name": "*.mail.google.com",    "name_value": "*.docs.google.comn*.mail.google.comn*.plus.google.comn*.sites.google.comn*.talkgadget.google.com",    "id": 2381394777,    "entry_timestamp": "2020-01-27T02:30:30.549",    "not_before": "2011-07-13T05:53:39",    "not_after": "2012-07-13T06:03:39",    "serial_number": "3e554a12000300002c7f",    "result_count": 6  }]

这个命令就像这样:

$ jq -r ".[] | .name_value" $DOMAIN/crt
-r标志告诉jq将输出直接写入标准输出,而不是将其格式化为JSON字符串。这个.[]遍历JSON文件中的数组,并且.name_value提取每个项的name_value字段。
最后,$DOMAIN/crt是jq命令的输入文件。要了解更多关于jq是如何工作的信息,请阅读它的手册
https://stedolan.github.io/jq/manual/
要将所有输出文件合并到主报告中,请编写这样的脚本:
#!/bin/bashPATH_TO_DIRSEARCH="/Users/vickieli/tools/dirsearch"DOMAIN=$1DIRECTORY=${DOMAIN}_reconecho "Creating directory $DIRECTORY."mkdir $DIRECTORYnmap_scan(){ nmap $DOMAIN > $DIRECTORY/nmap echo "The results of nmap scan are stored in $DIRECTORY/nmap."}dirsearch_scan(){ $PATH_TO_DIRSEARCH/dirsearch.py -u $DOMAIN -e php --simple-report=$DIRECTORY/dirsearch echo "The results of dirsearch scan are stored in $DIRECTORY/dirsearch."}crt_scan(){ curl "https://crt.sh/?q=$DOMAIN&output=json" -o $DIRECTORY/crt echo "The results of cert parsing is stored in $DIRECTORY/crt."}case $2 in nmap-only) nmap_scan ;; dirsearch-only) dirsearch_scan ;; crt-only) crt_scan ;; *) nmap_scan dirsearch_scan crt_scan ;; esacecho "Generating recon report from output files..."TODAY=$(date)echo "This scan was created on $TODAY" > $DIRECTORY/report 【1】echo "Results for Nmap:" >> $DIRECTORY/reportgrep -E "^s*S+s+S+s+S+s*$" $DIRECTORY/nmap >> $DIRECTORY/report 【2】echo "Results for Dirsearch:" >> $DIRECTORY/reportcat $DIRECTORY/dirsearch >> $DIRECTORY/report 【3】echo "Results for crt.sh:" >> $DIRECTORY/reportjq -r ".[] | .name_value" $DIRECTORY/crt >> $DIRECTORY/report 【4】
首先,我们创建一个名为report的新文件,并将今天的日期写入它【1】,以跟踪报告生成的时间。
然后,我们将nmap的结果和Dirsearch命令的结果附加到报告文件【2】中。
cat命令将文件的内容打印到标准输出,但是我们也可以使用它将文件的内容重定向到另一个文件【3】。
最后,我们从crt.sh报告中提取域名,并将其附加到报告文件【4】的末尾。
  • 扫描多个域

如果我们想同时扫描多个域该怎么办?在侦察一个目标时,我们可能从该组织的几个域名开始。
例如,我们知道脸书同时拥有facebook.com和fbcdn.net。但是我们当前的脚本允许我们一次只能扫描一个域。
我们需要编写一个工具,可以用一个命令扫描多个域,就像这样:
./recon.sh facebook.com fbcdn.net nmap-only
当我们像这样扫描多个域时,我们需要一种方法来区分哪些参数指定了扫描模式,哪些参数指定了目标域。
正如您已经从我介绍的工具中看到的,大多数工具允许用户通过使用命令行选项或标志来修改工具的行为,如-u和 --simple-report
  • getopts 命令行工具用法

getopts工具从命令行中解析单字符选项,如-m。

-u http://127.0.0.1选项变量名为u选项变量值为http://127.0.0.1在命令ls -l /home中-l  是一个修改命令行为的选项/home 是一个向命令提供特定数据(要列出的目录)的参数值
它的语法如下,其中OPTSTRING指定了getopts应该识别的选项字母,例如,如果它应该识别选项-m和-i,那么您应该把OPTSTRING写为mi。
OPTSTRING如果写为abc表示脚本正在寻找选项-a、和-b,-c且没有任何参数值。但是,如果 OPTSTRING是a:bc,则表示脚本正在寻找选项-a、-b和-c,但只-a需要一个参数值
如果您想要一个包含值的选项,字母后面应该有一个冒号,像这样:m:i(选项m和选项i,并且选项m包含值),getopts工具还会自动将选项变量存储到$OPTARG变量中,$OPTARG中存储选项变量或者选项变量的值,当选项有值时。
NAME表示存储选项的变量,是用于存储当前正在处理的选项的变量。虽然从技术上讲,此变量可以是任何您想要的名称,但通常命名为opt或option
getopts OPTSTRING<要识别的选项标志> NAME<存储当前正在处理的选项的变量>

我们可以将$OPTARG存储到一个名为MODE的变量中:

getopts "m:" OPTIONMODE=$OPTARG

例子为译者自行添加,为了帮助读者更好的理解getopts命令

例一:

现在,如果您使用-m标志运行shell脚本,那么该脚本将知道您正在指定一个扫描MODE!
#!/bin/bashOPTSTRING=":ab"while getopts ${OPTSTRING} opt; do  case ${opt} in    a)      echo "Option -a was triggered."      ;;    b)      echo "Option -b was triggered."      ;;    ?)      echo "Invalid option: -${OPTARG}."      exit 1      ;;  esacdone

侦察脚本编写(正则+getopts)2

让我们分解一下这个脚本:

OPTSTRING定义为:ab。这告诉脚本需要两个选项,-a和-b。这两个选项都不需要参数。
循环while getopts ${OPTSTRING} opt; do ... done就是getopts它的魔力所在。它将按顺序解析传递给脚本的选项。对于遇到的每个选项,getopts将其分配给opt变量,然后执行循环主体。
在循环内部,我们有一个case ${opt} in ... esac语句,负责处理每个选项。如果选项是a,则回显Option -a was triggered.。如果选项是b,则回显Option -b was triggered.。
这里有一个重要的部分:?)case 语句中的。在上下文中getopts,问号 (?) 是一个特殊字符,当传递了无效选项时(即,此脚本中除“a”或“b”之外的任何内容),该字符会被匹配。
当遇到这种无效选项时,getopts将该选项分配给OPTARG变量。将无效选项分配给后OPTARG,Invalid option: -${OPTARG}.将打印消息。然后使用 exit 终止脚本1,表示发生了错误。这样做的好处是脚本不仅在遇到无效选项时终止,而且还会通知用户他们传递的确切无效选项。

例二:

#!/bin/bashOPTSTRING=":a:b"while getopts ${OPTSTRING} opt; do  case ${opt} in    a)      echo "Option -a was ${OPTARG}."      ;;    b)      echo "Option -b was triggered."      ;;    ?)      echo "Invalid option: -${OPTARG}."      exit 1      ;;  esacdone

侦察脚本编写(正则+getopts)2

例三:

此例为了说明$OPTIND的意思。
$OPTIND代表的是下一个待处理参数的索引。当getopts命令开始处理命令行参数时,它会从位置1(即第一个参数)开始,并随着处理过程逐步递增这个变量的值。一旦getopts遇到了非选项参数(即不以-开头的参数),它会停止处理,并将$OPTIND设置为该非选项参数之后的位置。这样,你可以基于$OPTIND的值来访问那些未被getopts处理的额外参数
#!/bin/bashwhile getopts "a:b:" opt; do  case $opt in    a) echo "$OPTARG" ;;    b) echo "$OPTARG" ;;    ?) echo "Invalid option -$OPTARG" >&2 ;;  esacdone# $OPTIND现在指向第一个非选项参数shift $((OPTIND-1))# 现在$@只包含未被getopts处理的参数(如果有)for file in "$@"; do  echo "Processing file: $file"done

侦察脚本编写(正则+getopts)2

  • 多域扫描的shell脚本

为了实现我们的多域扫描功能,我们允许用户使用-m标志来指定扫描模式,假设所有其他参数都是域名。
在这里,我们告诉getopts识别标志是-m选项,并且这个选项应该包含一个输入值。
请注意,当getopts遇到非以-字符开头的参数时,它将停止解析参数,因此在运行脚本时,需要将扫描模式放在域参数之前:
./recon.sh -m nmap-only facebook.com fbcdn.net
接下来,我们将需要一种方法来读取每个域名参数并对它们执行扫描。我们用循环吧!
Bash有两种类型的循环:for循环和while循环。
for循环更适合于我们,因为我们已经知道通过循环的数量。通常,当已经有要遍历的次数或列表时,应该用for循环。
当您不确定要循环多少次,但希望指定执行应该停止的条件时,您应该使用while循环。
下面是bash中的for循环的语法。对于LIST_OF_VALUES中的每一项,bash将在do和done之间执行一次代码:
for i in LIST_OF_VALUESdo DO SOMETHINGdone

现在,让我们通过使用一个for循环来实现我们的功能

for i in "${@:$OPTIND:$#}"do # Do the scans for $idone
$0 代表脚本本身的名称,$1 代表传递给脚本的第一个参数,$2 代表第二个参数
字符$@表示包含脚本所有输入参数的数组,而$#是传递进的命令行的参数数量。
"${@:$OPTIND:$#}"将数组进行切片,以便它删除像 nmap-only的MODE参数,确保我们只遍历输入的域名部分。
我们创建了一个数组,它包含每个命令行参数,除了那些已经被getopts解析的参数(-m nmap-only),它将第一个参数的索引存储在$OPTIND的变量。
数组切片是一种从数组中提取子集的方法。在bash中,您可以使用此语法对数组进行切片(注意,命令周围的引号是必要的):
"${INPUT_ARRAY:START_INDEX:END_INDEX}"
$i变量表示参数数组中的当前项。然后,我们就可以循环了:
#!/bin/bashPATH_TO_DIRSEARCH="/Users/vickieli/tools/dirsearch"nmap_scan(){     nmap $DOMAIN > $DIRECTORY/nmap     echo "The results of nmap scan are stored in $DIRECTORY/nmap."}dirsearch_scan(){     $PATH_TO_DIRSEARCH/dirsearch.py -u $DOMAIN -e php --simple-report=$DIRECTORY/dirsearch     echo "The results of dirsearch scan are stored in $DIRECTORY/dirsearch."}crt_scan(){     curl "https://crt.sh/?q=$DOMAIN&output=json" -o $DIRECTORY/crt     echo "The results of cert parsing is stored in $DIRECTORY/crt."}getopts "m:" OPTIONMODE=$OPTARGfor i in "${@:$OPTIND:$#}" 【1】do     DOMAIN=$i     DIRECTORY=${DOMAIN}_recon     echo "Creating directory $DIRECTORY."     mkdir $DIRECTORY     case $MODE in         nmap-only)             nmap_scan             ;;         dirsearch-only)             dirsearch_scan             ;;         crt-only)             crt_scan             ;;         *)             nmap_scan             dirsearch_scan             crt_scan             ;;      esac     echo "Generating recon report for $DOMAIN..."     TODAY=$(date)     echo "This scan was created on $TODAY" > $DIRECTORY/report     if [ -f $DIRECTORY/nmap ];then 【2】         echo "Results for Nmap:" >> $DIRECTORY/report         grep -E "^s*S+s+S+s+S+s*$" $DIRECTORY/nmap >> $DIRECTORY/report     fi     if [ -f $DIRECTORY/dirsearch ];then 【3】         echo "Results for Dirsearch:" >> $DIRECTORY/report         cat $DIRECTORY/dirsearch >> $DIRECTORY/report     fi     if [ -f $DIRECTORY/crt ];then 【4】         echo "Results for crt.sh:" >> $DIRECTORY/report         jq -r ".[] | .name_value" $DIRECTORY/crt >> $DIRECTORY/report     fi done 【5】
for循环以for关键字do【1】开始,以done关键字【5】结束。请注意,我们还在报告部分中添加了几行,以查看是否需要生成每种类型的报告。
我们检查Nmap扫描、dirsearch扫描或crt.sh扫描的输出文件是否存在,因此我们可以确定是否需要为该扫描类型【2】 【3】 【4】生成报告。

原文始发于微信公众号(SecurityBug):侦察脚本编写(正则+getopts)2

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月20日13:36:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   侦察脚本编写(正则+getopts)2https://cn-sec.com/archives/2865264.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息