【保姆級(jí)Python教學(xué)】萬(wàn)物皆可 API

今天看到一個(gè)開(kāi)源項(xiàng)目,叫做 Command2API,感覺(jué)挺有意思的,分享給大家。

起源

關(guān)于這個(gè)項(xiàng)目為什么誕生,原 Repo 有這么一段:

以近期 Log4j 的 RCE 舉例,在內(nèi)網(wǎng)的安全測(cè)試中,由于網(wǎng)絡(luò)環(huán)境限制導(dǎo)致沒(méi)有 DNSLog 平臺(tái)可用,這時(shí)候做 Log4j 的漏洞驗(yàn)證就考慮直接查看 LDAP 服務(wù)是否有連接進(jìn)來(lái),但是現(xiàn)成的 JNDI 注入工具開(kāi)啟服務(wù)并沒(méi)有 API 可以直接拉取對(duì)應(yīng)服務(wù)的結(jié)果,這就導(dǎo)致需要人工去查看,很費(fèi)時(shí)間,再加上已經(jīng)寫(xiě)好 BurpSuite 被動(dòng)插件進(jìn)行掃描了,為了節(jié)省時(shí)間就簡(jiǎn)單寫(xiě)了這個(gè)腳本用于獲取 JNDI 工具的執(zhí)行結(jié)果并通過(guò) API 的形式返回,便于插件拉取結(jié)果進(jìn)行漏洞驗(yàn)證。

反正大意就是說(shuō),有些命令的執(zhí)行結(jié)果如果能夠通過(guò) HTTP的 API 暴露出來(lái),我們就能更方便地獲取到命令的執(zhí)行結(jié)果,在某些場(chǎng)景下會(huì)非常方便。

所以,這里作者寫(xiě)了這個(gè)項(xiàng)目。

原理

這個(gè)原理其實(shí)非常簡(jiǎn)單,就是用一個(gè) Python 線(xiàn)程開(kāi)啟 Web 服務(wù),一個(gè)線(xiàn)程執(zhí)行命令,通過(guò)全局變量與 Web 服務(wù)共享執(zhí)行命令的結(jié)果。

運(yùn)行

這里我們來(lái)運(yùn)行下看看效果吧。

首先需要下載下項(xiàng)目:

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

然后接著指定想運(yùn)行的命令和 API 運(yùn)行的端口就好了,樣例如下:

python Command2Api.py "執(zhí)行的命令" Web運(yùn)行的端口

注意,這里的 python 使用的 Python2,而不是 Python3,因?yàn)樵?xiàng)目引用了一個(gè)包叫 BaseHTTPServer,Python3 是沒(méi)有的。

這里我們執(zhí)行一個(gè) ping 命令來(lái)試試:

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

運(yùn)行結(jié)果如下:

可以看到,這里首先輸出了一個(gè)運(yùn)行的地址:

URL: http://HOST:8888/c1IvlLF9

這時(shí)候我們打開(kāi) http://localhost:8888/c1IvlLF9 看下。

可以看到控制臺(tái)結(jié)果就呈現(xiàn)在網(wǎng)頁(yè)里面了。

但是這個(gè)頁(yè)面沒(méi)法自動(dòng)刷新,需要點(diǎn)擊刷新來(lái)獲取最新的結(jié)果。

介紹完了。

所以,這個(gè)項(xiàng)目在某些情況下還是挺有用的。

比如說(shuō):

  • 內(nèi)網(wǎng)安全測(cè)試中,可以用于獲取 JNDI 工具的執(zhí)行結(jié)果并通過(guò)API的形式返回,可以更方便地觀測(cè)執(zhí)行結(jié)果。
  • 我們想監(jiān)控或?qū)崟r(shí)獲取某個(gè)命令行程序的輸出結(jié)果,比如 Scrapy 爬蟲(chóng)、比如 Web Server 等等,可以將其暴露出來(lái)。
  • 我們想快速分享某個(gè)程序的執(zhí)行結(jié)果,則可以通過(guò)這個(gè)命令配合 Ngrok 生成一個(gè)網(wǎng)站分享出去。

等等。

源碼解析

我們?cè)賮?lái)看看源碼吧,其實(shí)非常簡(jiǎn)單,一共就這些代碼:

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()

可以看到這個(gè)命令就是 Popen 執(zhí)行的,然后通過(guò) PIPE 將結(jié)果捕獲出來(lái)賦值為變量,然后同時(shí)另外一個(gè)線(xiàn)程啟動(dòng)服務(wù)器,將這個(gè)結(jié)果寫(xiě)入到 Response 里面。

就是這么簡(jiǎn)單的代碼,實(shí)現(xiàn)了如此便捷的功能。

優(yōu)化

不過(guò)我看這個(gè)項(xiàng)目還是有很多優(yōu)化空間的,簡(jiǎn)單總結(jié)下:

  • 現(xiàn)在支持的是 Python2 而不是 Python3。
  • 網(wǎng)頁(yè)結(jié)果不能自動(dòng)刷新。
  • 網(wǎng)頁(yè)結(jié)果是一個(gè)列表,和控制臺(tái)的結(jié)果格式不太統(tǒng)一。
  • 不能通過(guò) pip 來(lái)安全這個(gè)工具包。
  • 輸出結(jié)果的 HOST 可以?xún)?yōu)化一下,直接復(fù)制出來(lái)不好訪問(wèn)。
  • 可以配合 Ngrok 將結(jié)果進(jìn)行公開(kāi)暴露。
  • 如果能通過(guò)網(wǎng)頁(yè)來(lái)對(duì)命令進(jìn)行交互控制就更好了。

我看看如果有時(shí)間的話(huà),我可以試著將這個(gè)項(xiàng)目改寫(xiě)下并實(shí)現(xiàn)如上的一些優(yōu)化功能哈,到時(shí)候?qū)懲炅税l(fā)出來(lái)。

謝謝閱讀~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容