记录入门安全开发的学习笔记,供日后回顾。
命令行编程就是通过和用户交互 , 接收用户输入的数据,处理后,将结果反馈给用户。
比如我们使用sqlmap:
python sqlmap.py -u http://1.14.71.254:28829/sqli-labs/Less-1/?id=1 -D test_db -T test_tb -columns -batch
其中, -u、-D、-T、-columns 和 -batch 参数用于指定目标 URL 和要执行的操作。
命令行参数
命令行参数就是在运行程序时,用户在命令行(或终端)中输入的信息,通常以空格分隔,作为程序启动命令的一部分直接提供给程序。
命令行参数通常分为:
- 位置参数
按照特定的顺序传递给程序的参数。
- 选项参数
以“-”或“--”开头的参数,是可选的,并且可以以任意顺序提供给程序。
- 参数值
参数值是与选项参数相关联的具体值,通常与选项参数之间用空格分开,或者使用等号连接。比如:--name John --age 30
用户交互
接下来我们通过一个示例来看看几种与用户交互的方式:
例:编写一个 rce漏洞的 poc
思路:
为测试一个网站是否存在 RCE 漏洞,我们首先需要提供网站的 URL,然后通过执行命令并检查回显来判断漏洞是否存在。因此,我们需要接收两个用户输入的参数:URL和要执行的命令。
input接收
url = input("请输入url:").strip()
cmd = input("请输入要运行的命令:").strip()
print(f"正在对{url}网站执行{cmd}命令")
print("命令执行完成")
可以加个提示语/banner信息 ,然后封装到函数里
def main():
banner = """cve-2022-4346-rce
使用方法 : 根据提示依次输入url和命令"""
print(banner)
url = input("请输入url:").strip()
cmd = input("请输入要运行的命令:").strip()
print(f"正在对{url}网站执行{cmd}命令")
print("命令执行完成")
if __name__ == "__main__":
main()
随便输入一个url和命令,运行:
sys模块
import sys
print(sys.argv) # 接收py脚本传进来的参数 , 返回一个列表 , 一般用来获取命令行参数
现在我们把input改为sys.argv
import sys
def main():
banner = """cve-2022-4346-rce
使用方法 : 根据提示依次输入url和命令"""
print(banner)
if len(sys.argv) == 3:
url = sys.argv[1]
cmd = sys.argv[2]
print(f"正在对{url}网站执行{cmd}命令")
print("执行完毕")
else:
print("请根据提示输入信息")
if __name__ == "__main__":
main()
此时,可以使用“-h”来查看相关信息了:python3 main.py -h
执行:
但是还不够,别人都有对应的参数,比如:--url、--file、--dump这种,这是怎么实现的?
argparse模块
完成参数解析一般用到getopt, optparse和argparse。其中,argparse 基于 optparse , 是Python3.2推出的命令行参数解析模块。该模块不但可以用来写poc/exp , 还可以写一些命令行的渗透测试工具。
# 导入模块
import argparse
# 实例化一个对象 , 并添加命令行的描述信息,用来介绍脚本是干嘛的
parser = argparse.ArgumentParser(description="脚本的提示信息")
# 调用parse_args方法
parser.parse_args()
因为我们还没有定义其它参数,所以现在只有“-h”
位置参数
位置参数一般是工具中必须传入的参数 。
import argparse
parser = argparse.ArgumentParser()
# 添加一个参数,参数名叫做url
parser.add_argument("url")
# 解析参数,得到一个args对象
args = parser.parse_args()
# 通过 对象.参数名 调用
print(args.url)
可以给参数设置一些属性:
parser.add_argument("url", help="input a url",type=str)
# 默认参数接收的值都是字符串类型, 如果需要其他类型 , 使用type指定
可选参数
import argparse
parser = argparse.ArgumentParser()
# 添加一个参数,参数名叫做url
parser.add_argument("--url", help="input a url")
# 解析参数,得到一个args对象
args = parser.parse_args()
print(args.url) # 默认不指定值的时候为None
短选项
比如--help的短选项是-h,--url的短选项是-u
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="input a url")
args = parser.parse_args()
print(args.url)
退出函数
import sys
sys.exit(0) # 程序会直接退出 , 安全退出
sys.exit(1) # 程序会直接退出 , 报错退出
示例
import argparse
def main(url, cmd):
"""对指定url执行命令"""
print(f"正在对{url}网站执行{cmd}命令")
print("执行完毕")
if __name__ == "__main__":
banner = """
.__ ____
___ __| |/_ | _______ __
\ \/ / | | |/ \ \/ /
> <| |_| | | \ /
/__/\_ \____/___|___| /\_/
\/ \/
"""
print(banner)
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url")
parser.add_argument("-c", "--cmd")
args = parser.parse_args()
main(args.url, args.cmd)
banner中的内容为字符画,在线生成字符画的网站链接我贴在文末了。
效果:
完善一下argparse模块的代码:
import argparse
import textwrap
def main(url, cmd):
# 简易模仿代码
"""真正具体对指定url执行命令的代码"""
print(f"正在对{url} 网站执行{cmd} 这条系统命令")
print("命令执行完成,命令的回显: root")
if __name__ == '__main__':
banner = """
.__ ____
___ __| |/_ | _______ __
\ \/ / | | |/ \ \/ /
> <| |_| | | \ /
/__/\_ \____/___|___| /\_/
\/ \/
"""
print(banner)
parser = argparse.ArgumentParser(description='thinkphp5 rce exp',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent(
'''example:cve-2022-4334-rce.py -u http://192.168.1.108 -c id'''))
parser.add_argument("-u", "--url", dest="url", type=str, help=" example:http: // www.mhx.com")
parser.add_argument("-c", "--cmd", dest="cmd", type=str, default="whoami", help="default=whoami example: id")
args = parser.parse_args()
main(args.url, args.cmd)
import textwrap
的作用是帮助格式化 argparse.ArgumentParser
的帮助信息。通过设置 formatter_class=argparse.RawDescriptionHelpFormatter
和 epilog=textwrap.dedent('''example:cve-2022-4334-rce.py -u http://192.168.1.108 -c id''')
,来更好地展示命令行工具的使用示例。
效果:
上述代码其实还缺少一些重要内容。比如,当用浏览器访问网站时,如果SSL证书过期,通常需要二次确认。在使用requests模块时,默认的verify
参数为True
,我们需要将其手动设置为False
。另外,还可以设置其它参数,比如超时参数等。
此外,并不是所有网站都能正常访问,因此在代码中需要考虑请求失败的情况,并进行相应处理。可以通过在代码中添加try ... except
语句来实现这一点。
try:
response = requests.post(url, headers=headers, cookies=cookies, verify=False, timeout=5,
data=data, allow_redirects=False)
print(response.text)
except Exception as e:
print(e)
字符画在线生成
Text to ASCII Art Generator (TAAG)
如有错漏,欢迎指正。