Let sslproxy sniff Microsoft's implementation

This commit is contained in:
Michael Herrmann
2021-12-09 15:48:09 +01:00
parent 08abfabe71
commit 1650394d83
2 changed files with 88 additions and 20 deletions
+20 -3
View File
@@ -35,8 +35,25 @@ Then:
python sslproxy.py
Then you can open `https://localhost:8443` in the browser.
Then you can add the REST source (note the `httpS`):
To add the REST source:
winget source add -n wpr -a https://localhost:8443/api/ -t "Microsoft.Rest"
winget source add -n "winget-pkgs-restsource" -a https://localhost:8443/api/ -t "Microsoft.Rest"
### Sniff Microsoft's implementation
Look at the `msstore` source shown by `winget source list`. Typically, it is:
https://storeedgefd.dsx.mp.microsoft.com/v9.0
Start `sslproxy` as a man-in-the-middle proxy for the above domain:
python sslproxy.py 8444 storeedgefd.dsx.mp.microsoft.com 443
Then you can add the proxied source via:
winget source add -n ms -a https://localhost:8444/v9.0 -t "Microsoft.Rest"
(Note that we used the path `/v9.0` from above.)
Now you can inspect the traffic in the output of `sslproxy` when you perform
`winget` commands.
+68 -17
View File
@@ -1,33 +1,84 @@
import socket, ssl
"""
Usage:
python sslproxy [local_port] [dest_host] [dest_port]
The defaults are local_port=8443, dest_host=localhost, dest_port=8000.
"""
import socket, ssl, sys
from functools import partial
from threading import Thread
def forward(source, destination):
string = b' '
while string:
string = source.recv(1024)
if string:
destination.sendall(string)
if len(sys.argv) > 1:
local_port = int(sys.argv[1])
else:
local_port = 8443
if len(sys.argv) > 2:
dest_host = sys.argv[2]
else:
dest_host = 'localhost'
if len(sys.argv) > 3:
dest_port = int(sys.argv[3])
else:
dest_port = 8000
def forward(source, destination, prefix=''):
data = b' '
while data:
try:
data = source.recv(1024)
except ConnectionResetError:
break
if data:
decoded = data.decode('utf-8')
for line in decoded.split('\n'):
print(prefix + line)
decoded = decoded.replace(
f'\nHost: localhost:{local_port}',
f'\nHost:{dest_host}'
)
destination.sendall(decoded.encode('utf-8'))
else:
source.shutdown(socket.SHUT_RD)
destination.shutdown(socket.SHUT_WR)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="conf/localhost.cert", keyfile="conf/localhost.key")
local_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
local_context.load_cert_chain(
certfile="conf/localhost.cert", keyfile="conf/localhost.key"
)
if dest_port == 443:
dest_context = ssl.create_default_context()
else:
dest_context = None
bindsocket = socket.socket()
bindsocket.bind(('', 8443))
bindsocket.bind(('', local_port))
bindsocket.listen(5)
bindsocket.settimeout(.5)
print("Forwarding https://localhost:8443 -> http://localhost:8000")
print(f'Forwarding localhost:{local_port} -> {dest_host}:{dest_port}')
while True:
try:
newsocket, fromaddr = bindsocket.accept()
client_socket = context.wrap_socket(newsocket, server_side=True)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.connect(('localhost', 8000))
Thread(target=forward, args=(client_socket, server_socket)).start()
Thread(target=forward, args=(server_socket, client_socket)).start()
try:
newsocket, fromaddr = bindsocket.accept()
client = local_context.wrap_socket(newsocket, server_side=True)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect((dest_host, dest_port))
if dest_context:
server = dest_context.wrap_socket(server, server_hostname=dest_host)
Thread(
target=partial(forward, prefix='-> '), args=(client, server)
).start()
Thread(
target=partial(forward, prefix='<- '), args=(server, client)
).start()
except socket.timeout:
pass
except KeyboardInterrupt:
break