明天看到一个开源我的项目,叫做 Command2API,感觉挺有意思的,分享给大家。

起源

对于这个我的项目为什么诞生,原 Repo 有这么一段:

以近期 Log4j 的 RCE 举例,在内网的平安测试中,因为网络环境限度导致没有 DNSLog 平台可用,这时候做 Log4j 的破绽验证就思考间接查看 LDAP 服务是否有连贯进来,然而现成的 JNDI 注入工具开启服务并没有 API 能够间接拉取对应服务的后果,这就导致须要人工去查看,很费时间,再加上曾经写好 BurpSuite 被动插件进行扫描了,为了节省时间就简略写了这个脚本用于获取 JNDI 工具的执行后果并通过 API 的模式返回,便于插件拉取后果进行破绽验证。

反正粗心就是说,有些命令的执行后果如果可能通过 HTTP的 API 裸露进去,咱们就能更不便地获取到命令的执行后果,在某些场景下会十分不便。

所以,这里作者写了这个我的项目。

原理

这个原理其实非常简单,就是用一个 Python 线程开启 Web 服务,一个线程执行命令,通过全局变量与 Web 服务共享执行命令的后果。

运行

这里咱们来运行下看看成果吧。

首先须要下载下我的项目:

git clone https://github.com/gh0stkey/Command2API.git

而后接着指定想运行的命令和 API 运行的端口就好了,样例如下:

python Command2Api.py "执行的命令" Web运行的端口

留神,这里的 python 应用的 Python2,而不是 Python3,因为原我的项目援用了一个包叫 BaseHTTPServer,Python3 是没有的。

这里咱们执行一个 ping 命令来试试:

python Command2Api.py "ping www.baidu.com" 8888 

运行后果如下:

能够看到,这里首先输入了一个运行的地址:

URL: http://HOST:8888/c1IvlLF9

这时候咱们关上 http://localhost:8888/c1IvlLF9 看下。

能够看到控制台后果就出现在网页外面了。

然而这个页面没法主动刷新,须要点击刷新来获取最新的后果。

介绍完了。

所以,这个我的项目在某些状况下还是挺有用的。

比如说:

  • 内网平安测试中,能够用于获取 JNDI 工具的执行后果并通过API的模式返回,能够更不便地观测执行后果。
  • 咱们想监控或实时获取某个命令行程序的输入后果,比方 Scrapy 爬虫、比方 Web Server 等等,能够将其裸露进去。
  • 咱们想疾速分享某个程序的执行后果,则能够通过这个命令配合 Ngrok 生成一个网站分享进来。

等等。

源码解析

咱们再来看看源码吧,其实非常简单,一共就这些代码:

import subprocessimport BaseHTTPServerimport SimpleHTTPServerimport cgiimport threadingimport sysimport stringimport randoml = []uri = '/' + ''.join(random.sample(string.ascii_letters+string.digits,8))class thread(threading.Thread):  def __init__(self, threadname, command):    threading.Thread.__init__(self, name='Thread_' + threadname)    self.threadname = int(threadname)    self.command = command  def run(self):    global l    ret = subprocess.Popen(      self.command,      shell=True,      stdin=subprocess.PIPE,      stdout=subprocess.PIPE,      stderr=subprocess.PIPE    )    for i in iter(ret.stdout.readline, b""):      res = i.decode().strip()      print(res)      l.append(res)class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):  def do_GET(self):    global l    if self.path == uri:      self.send_response(200)      self.send_header('Content-Type', 'text/plain')      self.end_headers()      self.wfile.write(l)if __name__ == '__main__':  # New Thread: Get Command Result  t1 = thread('1', sys.argv[1])  t1.start()  # Webserver  port = int(sys.argv[2])  print("URL: http://HOST:{0}{1}".format(port, uri))  Handler = ServerHandler  httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', port), Handler)  httpd.serve_forever()

能够看到这个命令就是 Popen 执行的,而后通过 PIPE 将后果捕捉进去赋值为变量,而后同时另外一个线程启动服务器,将这个后果写入到 Response 外面。

就是这么简略的代码,实现了如此便捷的性能。

优化

不过我看这个我的项目还是有很多优化空间的,简略总结下:

  • 当初反对的是 Python2 而不是 Python3。
  • 网页后果不能主动刷新。
  • 网页后果是一个列表,和控制台的后果格局不太对立。
  • 不能通过 pip 来平安这个工具包。
  • 输入后果的 HOST 能够优化一下,间接复制进去不好拜访。
  • 能够配合 Ngrok 将后果进行公开裸露。
  • 如果能通过网页来对命令进行交互管制就更好了。

我看看如果有工夫的话,我能够试着将这个我的项目改写下并实现如上的一些优化性能哈,到时候写完了收回来。

谢谢浏览~