1

According to wikipedia.org's article on X.509 certificates, "There are implementation errors with X.509 that allow e.g. falsified subject names using null-terminated strings Marlinspike Blackhat 2009 or code injections attacks in certificates." My question is... how do I create a CSR with null bytes within them?

Here's a CSR that does have one in it:

-----BEGIN CERTIFICATE REQUEST-----
MIIBSTCBtQIBADAQMQ4wDAYDVQQKDAVhYgBjZDCBnTALBgkqhkiG9w0BAQEDgY0A
MIGJAoGBALoqjrGPCxX2oWX8APXhB3dzKJAXWHKWSlMWDw1whCP+EpsdFY2pTq+D
RnX8wRIP2yssIii/4FwsDxjcjlYMpSqYBPnEq3Lql/7LeW5ulLn4wk4Gnd4B55WP
BLveMNCORZXtE5rNJISTRMHYZKp7sLOPFlE3Gb5G/o/rkxSqOKOPAgMBAAEwCwYJ
KoZIhvcNAQEFA4GBAB0CX/T2wBTHHE6dcCFwzXsVkqkoewQbLjDLoAjCBy7nFrCI
6+kLPj7zcYi6f+Jg+OcFMl0Oat+2iO7OARSib3S0WyuAFpJQQwZIiG9RISy2HF1A
jQPuWvOan1GsY74Dn0kac6BIaWlY0/9h/iIcl4BiUaFrW+xUinKGWofsdq8l
-----END CERTIFICATE REQUEST-----

According to asn1parse the value corresponding to the organizationName has a length of 5 even though the string displayed has a length of four. The thing is, there's a null byte between the ab and the cd. That CSR was generated with a library called phpseclib but I'd like to know how to generate similar CSR's with OpenSSL or some other more standardized tool.

I tried this but it didn't work:

openssl req -new -key privkey.pem -out test.csr -subj "/O=ab\000cd"

That got me this:

-----BEGIN CERTIFICATE REQUEST-----
MIICVzCCAT8CAQAwEjEQMA4GA1UEChMHYWIwMDBjZDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKe9z81r0pvpqN98WinJVAphD0bRqi1W6OrEh9rx0DPO
RILofZwLP11d8vot19VMHBqB+kQuhtWKc/2Te+F1fgy1NJjcF+tjErE038zMd4O6
sU7QiVuFKRceznaXiL2BKm5nCR5FBMj2gBu2WJ61mUKEkNYEvj7QtcMc/VUTYISq
D2DFoGmSjgltCtUyMqaSGtS6f2fqHFBvxVwLBDm+XSYYLrEREk2PmM1RbFY1b9fO
lKnrvRIN4X+RbqG9iF88Ax5T0L2/D1OjLD24eFY8m/ecrsMwxCAa9FL+oKIvT7M0
OGK+LWOkPpjKwegnppFYGOCEfLBDocSgD8z2AuV24usCAwEAAaAAMA0GCSqGSIb3
DQEBBQUAA4IBAQBmQwFqS8L4YO17hpTZTr/mKq0Mgzzf8PCI6d1OtRgKUM5LbFBX
WqCJSUzSrkCGQdMdFA9l20jw91gxaeLiEDbAS+1I8agel/TD6Hic5457HjyGbPx4
usqm0/c1/JRreG/1dyh2K6/TFPIN8dN++dLohmZlRWZdIMC0D/KNls5M++DiWqw3
J5S24BWIC6FOUsAs5EImd30+s4wXcL+uqlRmyQVZ3C+JI8ZBl5HuIKCLmS2d3rhG
/CBwlZHH4fyeYUpeWec6HUNjfvnJ8amDFyKPlbTgcSSEpXBBPGP4EJ+zrWFjZRe3
YDCxZ0RdBHjKsYzbJZDJEOe9YML5HqoXY1pr
-----END CERTIFICATE REQUEST-----

ie. the organizationName is ab000cd - not ab\00cd.

neubert
  • 1,605
  • 3
  • 18
  • 36

1 Answers1

4

These things are normally done programmatically. The command-line apps from OpenSSL are restricted in many ways, and don't give access to the full power of the underlying library. If you look at the source code, you will find the implementation of the req command in apps/req.c. For subject name parsing, that command relies on the parse_name() function (defined in apps/apps.c). That function internally builds the name elements as so many null-terminated C strings, which, by definition, cannot contain a null byte. Therefore, no possible way to achieve what you seek with that tool alone.

So one option is to simply download OpenSSL's source code, patch apps/req.c to include a null byte where you want it, compile it and run it. This will require a bit of knowledge of C. You will want to use the X509_NAME_add_entry_by_txt() function (or one of its acolytes), with an explicit len parameter (not -1) to use as "string" a sequence of bytes which includes your null byte. If you look at parse_name() in apps/apps.c, you will see that it invokes X509_NAME_add_entry_by_NID() with len set to -1: that's the exact point that you'll want to change.

Another option is to generate a "normal" certificate request, with another letter where you would like to have your null byte (e.g. a 'Z'). Then, make sure to convert your request to binary ("DER") format; then use a binary file editor to replace the 'Z' with a byte of value 0; then recompute the signature so that it matches the new request contents. This last step can be done with basic Linux command-line tools (dd for file surgery, sha1sum to get a new hash, dc to do the big integer arithmetics) but you have to master both ASN.1/DER and PKCS#1, and if you did then you would not have asked the question you asked.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • openssl (which asker has) can (probably more easily) do the hash and signature (for RSA including ASN.1 and padding); see my answer and the asker's recap to the very similar question http://security.stackexchange.com/questions/58717/what-part-of-the-csr-is-hashed-in-order-to-create-its-signature/58735 . Also for a change this small instead of patching and recompiling openssl, you could just run it under a debugger and tweak the data at the right place. – dave_thompson_085 Jul 27 '14 at 22:10