Все доступно API

Python API Apache Log4j
Все доступно API

Сегодня я увидел проект с открытым исходным кодом под названием Command2API, который очень интересен, и я хочу поделиться им с вами.

источник

Что касается того, почему родился этот проект, в оригинальном репо есть этот абзац:

Взяв в качестве примера недавний RCE Log4j, в тесте безопасности интрасети платформа DNSLog недоступна из-за ограничений сетевой среды.В настоящее время при проверке уязвимости Log4j считается, что необходимо напрямую проверить, Подключен сервис LDAP, но включен готовый инструмент JNDI-инъекций.Нет API для сервиса, чтобы напрямую подтягивать результаты соответствующего сервиса, что требует ручного просмотра, что занимает очень много времени.Кроме того, BurpSuite для сканирования написан пассивный плагин В целях экономии времени этот скрипт написан просто для получения Результат выполнения JNDI-инструмента возвращается в виде API, что удобно плагинам для подтягивания результатов на наличие уязвимости проверка.

В любом случае, общая идея заключается в том, что если результаты выполнения некоторых команд могут быть выставлены через HTTP API, мы можем более легко получить результаты выполнения команд, что очень удобно в некоторых сценариях.

Итак, вот автор написал этот проект.

принцип

Этот принцип на самом деле очень прост: использовать поток Python для запуска веб-сервиса, поток для выполнения команды и делиться результатом выполнения команды с веб-сервисом через глобальные переменные.

бегать

Давайте запустим его здесь и посмотрим на эффект.

Сначала вам нужно скачать следующие элементы:

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, такой как веб-сервер и т. д., которые могут быть раскрыты.
  • Если мы хотим быстро поделиться результатом выполнения программы, мы можем использовать эту команду для создания веб-сайта, которым можно поделиться с 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.
  • ХОСТ выходного результата можно оптимизировать, и получить к нему прямой доступ путем копирования непросто.
  • Результаты могут быть опубликованы с помощью Ngrok.
  • Было бы еще лучше, если бы команды можно было интерактивно контролировать через веб-страницу.

Я посмотрю, если у меня будет время, я могу попробовать переписать этот проект и реализовать некоторые из вышеперечисленных функций оптимизации, и я вышлю его, когда закончу его писать.

Спасибо за чтение~

Для более интересного контента, пожалуйста, обратите внимание на мои публичные аккаунты «Coder of Attack» и «Cui Qingcai丨Jing Mi».