Merge pull request #8142 from FiloSottile/filippo/updates
[update] fix (unexploitable) BB'06 vulnerability in rsa_verify
This commit is contained in:
		
						commit
						032f232626
					
				
							
								
								
									
										30
									
								
								test/test_update.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								test/test_update.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Allow direct execution
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import unittest
 | 
				
			||||||
 | 
					sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					from youtube_dl.update import rsa_verify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestUpdate(unittest.TestCase):
 | 
				
			||||||
 | 
					    def test_rsa_verify(self):
 | 
				
			||||||
 | 
					        UPDATES_RSA_KEY = (0x9d60ee4d8f805312fdb15a62f87b95bd66177b91df176765d13514a0f1754bcd2057295c5b6f1d35daa6742c3ffc9a82d3e118861c207995a8031e151d863c9927e304576bc80692bc8e094896fcf11b66f3e29e04e3a71e9a11558558acea1840aec37fc396fb6b65dc81a1c4144e03bd1c011de62e3f1357b327d08426fe93, 65537)
 | 
				
			||||||
 | 
					        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'versions.json'), 'rb') as f:
 | 
				
			||||||
 | 
					            versions_info = f.read().decode()
 | 
				
			||||||
 | 
					        versions_info = json.loads(versions_info)
 | 
				
			||||||
 | 
					        signature = versions_info['signature']
 | 
				
			||||||
 | 
					        del versions_info['signature']
 | 
				
			||||||
 | 
					        self.assertTrue(rsa_verify(
 | 
				
			||||||
 | 
					            json.dumps(versions_info, sort_keys=True).encode('utf-8'),
 | 
				
			||||||
 | 
					            signature, UPDATES_RSA_KEY))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    unittest.main()
 | 
				
			||||||
							
								
								
									
										34
									
								
								test/versions.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								test/versions.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "latest": "2013.01.06", 
 | 
				
			||||||
 | 
					    "signature": "72158cdba391628569ffdbea259afbcf279bbe3d8aeb7492690735dc1cfa6afa754f55c61196f3871d429599ab22f2667f1fec98865527b32632e7f4b3675a7ef0f0fbe084d359256ae4bba68f0d33854e531a70754712f244be71d4b92e664302aa99653ee4df19800d955b6c4149cd2b3f24288d6e4b40b16126e01f4c8ce6", 
 | 
				
			||||||
 | 
					    "versions": {
 | 
				
			||||||
 | 
					        "2013.01.02": {
 | 
				
			||||||
 | 
					            "bin": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.02/youtube-dl", 
 | 
				
			||||||
 | 
					                "f5b502f8aaa77675c4884938b1e4871ebca2611813a0c0e74f60c0fbd6dcca6b"
 | 
				
			||||||
 | 
					            ], 
 | 
				
			||||||
 | 
					            "exe": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.02/youtube-dl.exe", 
 | 
				
			||||||
 | 
					                "75fa89d2ce297d102ff27675aa9d92545bbc91013f52ec52868c069f4f9f0422"
 | 
				
			||||||
 | 
					            ], 
 | 
				
			||||||
 | 
					            "tar": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.02/youtube-dl-2013.01.02.tar.gz", 
 | 
				
			||||||
 | 
					                "6a66d022ac8e1c13da284036288a133ec8dba003b7bd3a5179d0c0daca8c8196"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }, 
 | 
				
			||||||
 | 
					        "2013.01.06": {
 | 
				
			||||||
 | 
					            "bin": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.06/youtube-dl", 
 | 
				
			||||||
 | 
					                "64b6ed8865735c6302e836d4d832577321b4519aa02640dc508580c1ee824049"
 | 
				
			||||||
 | 
					            ], 
 | 
				
			||||||
 | 
					            "exe": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.06/youtube-dl.exe", 
 | 
				
			||||||
 | 
					                "58609baf91e4389d36e3ba586e21dab882daaaee537e4448b1265392ae86ff84"
 | 
				
			||||||
 | 
					            ], 
 | 
				
			||||||
 | 
					            "tar": [
 | 
				
			||||||
 | 
					                "http://youtube-dl.org/downloads/2013.01.06/youtube-dl-2013.01.06.tar.gz", 
 | 
				
			||||||
 | 
					                "fe77ab20a95d980ed17a659aa67e371fdd4d656d19c4c7950e7b720b0c2f1a86"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -15,33 +15,17 @@ from .version import __version__
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def rsa_verify(message, signature, key):
 | 
					def rsa_verify(message, signature, key):
 | 
				
			||||||
    from struct import pack
 | 
					 | 
				
			||||||
    from hashlib import sha256
 | 
					    from hashlib import sha256
 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert isinstance(message, bytes)
 | 
					    assert isinstance(message, bytes)
 | 
				
			||||||
    block_size = 0
 | 
					    byte_size = (len(bin(key[0])) - 2 + 8 - 1) // 8
 | 
				
			||||||
    n = key[0]
 | 
					    signature = ('%x' % pow(int(signature, 16), key[1], key[0])).encode()
 | 
				
			||||||
    while n:
 | 
					    signature = (byte_size * 2 - len(signature)) * b'0' + signature
 | 
				
			||||||
        block_size += 1
 | 
					    asn1 = b'3031300d060960864801650304020105000420'
 | 
				
			||||||
        n >>= 8
 | 
					    asn1 += sha256(message).hexdigest().encode()
 | 
				
			||||||
    signature = pow(int(signature, 16), key[1], key[0])
 | 
					    if byte_size < len(asn1) // 2 + 11:
 | 
				
			||||||
    raw_bytes = []
 | 
					 | 
				
			||||||
    while signature:
 | 
					 | 
				
			||||||
        raw_bytes.insert(0, pack("B", signature & 0xFF))
 | 
					 | 
				
			||||||
        signature >>= 8
 | 
					 | 
				
			||||||
    signature = (block_size - len(raw_bytes)) * b'\x00' + b''.join(raw_bytes)
 | 
					 | 
				
			||||||
    if signature[0:2] != b'\x00\x01':
 | 
					 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
    signature = signature[2:]
 | 
					    expected = b'0001' + (byte_size - len(asn1) // 2 - 3) * b'ff' + b'00' + asn1
 | 
				
			||||||
    if b'\x00' not in signature:
 | 
					    return expected == signature
 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
    signature = signature[signature.index(b'\x00') + 1:]
 | 
					 | 
				
			||||||
    if not signature.startswith(b'\x30\x31\x30\x0D\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'):
 | 
					 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
    signature = signature[19:]
 | 
					 | 
				
			||||||
    if signature != sha256(message).digest():
 | 
					 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
    return True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def update_self(to_screen, verbose, opener):
 | 
					def update_self(to_screen, verbose, opener):
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user