Recovered from the older tannerjc.net wiki snapshot dated January 23, 2016.

 All RPM packages produced by Red Hat are digitally signed by a GnuPG key that
 ensures extra authenticity of the package.  An unsigned RPM package will
 contain three authenticity fields:

 - a SHA1 digest of the header
 - a MD5 digest of the cpio payload (package contents)
 - the size of the package (comprised of the lead, signatures, and cpio payload)

 When RPM does a verification of the package prior to installing the
 package, it does a size comparison, and then computes the SHA1 digest and MD5
 digest to ensure nothing has been tampered with.  The weakest parts here are
 the size and MD5 checks.  SHA1 collisions are much more difficult to produce.
 So even if an attacker were able to change the payload to create an MD5
 collision and sufficiently pad the data in order to pass the size checks, they
 would still have to deal with the SHA1 protection.

 With a GPG-signed RPM this becomes even harder as they have to somehow fake
 the GPG signature.  There are two digital signatures embedded in each RPM
 package: the first for the header (Header V3 DSA signature), the second for
 the archive contents (V3 DSA signature).

 A GPG key ID is not resistant to collision, however there are a number of
 steps that would need to be taken by the end user in order for a trojan,
 signed, RPM to be installed.  The end user would have to install the faked GPG
 key to their public keyring, which would have to be done manually using either
 rpm directly or yum.  Because GPG keys are stored in the rpm database itself
 (in /var/lib/rpm/Pubkeys), this cannot be done by simply installing a GPG
 key via GnuPG itself, and this also needs to be done as the root user.

 As an example, assume a user were to install a package from a third-party
 repository that would add the control files for yum and install a GPG key on
 the system.  This would result in that repository's GPG key being placed in
 /etc/pki/rpm-gpg/, but it does not get installed unless it is done manually by
 the user (rpm --import, as root) or via yum.  In the case of yum, the end user
 would have to use the -y option to have that key automatically installed
 without verification; in the default operation it will prompt for the user to
 import the key (again, as root unless the user has sudo privileges to run rpm
 or yum).  At this point, even if there were a GPG key ID collision, it would
 be added to the RPM database as a trusted key; it would not replace a trusted
 key because the key is installed based on it's signature, not the key ID.

 Because the use of GPG keys in RPM packages has existed for years, all Linux
 vendors and nearly all third-party repositories utilize it.  With the added
 protection of the GPG signatures to RPM packages, even if an MD5 collision
 were found that allowed for the payload to be changed, the additional checks
 would make it impossible to fully (and automatically) spoof a rogue RPM
 package as legitimate.  This would take a great amount of social engineering
 and technical competence to pull off.  To mitigate any concerns about this
 issue, RPM packages can be examined using rpm -Kv prior to installation, and
 the -y option to yum should not be used unless installing exclusively from
 trusted repositories, such as RHN.

 Finally, rpm -Kv provides output like the following:

 % rpm -Kv bind-9.5.1-0.8.b2.fc10.x86_64.rpm
 bind-9.5.1-0.8.b2.fc10.x86_64.rpm:
     Header V3 DSA signature: OK, key ID 4ebfc273
     Header SHA1 digest: OK (22d5463cf8fad7068ad3febd188406eb0a9d665f)
     MD5 digest: OK (4811425978dadcd880fe405577415035)
     V3 DSA signature: OK, key ID 4ebfc273

 which makes it very easy to determine if a) the key is known and in the
 database (V3 DSA signature would indicate an unknown key if it were not), and
 b) whether or not it has been tampered with.

ganglia

rpmfluff

example1

example2

pre style=color:blue

  • !/usr/bin/python

import rpmfluff import popen2 import pdb import random

  • foo = rpmfluff.SimpleRpmBuild(foo, 0.1, 1)

  • foo.make() def createRpms(name, payloadfile, payloadpath, versions): print + name

    for i in range(1,versions): #packagename = name + str(i) packagename = name #foo = rpmfluff.SimpleRpmBuild(foo, 0.1, 1) print packagename foo = rpmfluff.SimpleRpmBuild(packagename, i, 1)

      # Add a directive to create a directory
      foo.create_parent_dirs(/tmp/files)
    
      # Add a simple hello world file
      #foo.add_simple_payload_file()
    
      # Define a file and it's contents
      fakefile = rpmfluff.SourceFile(payloadfile, 'version: ' + str(i) + '\ntest test test \n')
      # Add the file to the rpm
      #foo.add_installed_file(installPath = 'usr/share/doc/hello-wiki.txt',
      foo.add_installed_file(installPath = payloadpath + payloadfile,
                  sourceFile = fakefile,
                  mode=None,
                  createParentDirs=True,
                  subpackageSuffix=None,
                  isConfig=False,
                  isDoc=False,
                  isGhost=False)
    
      # Build rpm
      foo.make()
    

def getRandomNames():

words = []
file = open(words.txt)

while 1:
    lines = file.readlines(100000)
    if not lines:
        break
    for line in lines:
        #line.rstrip(\n\r)
        line = line.rstrip(\r\n)
        #print line
        words.append(line)
        #pdb.set_trace()
        #pass # do something

random.shuffle(words)
random.shuffle(words)
return words

def createRandomRpms(quantity):

names = getRandomNames()

for i in range(0, quantity):
    print creating  + names[i]
    createRpms(names[i], names[i] + -file, usr/share/doc/ + names[i], random.randint(2, 10))

createRandomRpms(10)