明天看到一个开源我的项目,叫做 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 subprocess
import BaseHTTPServer
import SimpleHTTPServer
import cgi
import threading
import sys
import string
import random
l = []
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 将后果进行公开裸露。
- 如果能通过网页来对命令进行交互管制就更好了。
我看看如果有工夫的话,我能够试着将这个我的项目改写下并实现如上的一些优化性能哈,到时候写完了收回来。
谢谢浏览~