RSA PKCS1 v1.5 decryption implementation does not detect ciphertext modification by prepending \0-bytes to ciphertexts
Hi there,
Another issue in RSA PKCS1 v1.5. Pike does not bork on ciphertexts that have been modified with prepended 0-bytes in their ciphertext.
A small test-case:
int main() {
string key = "30820943020100300d06092a864886f70d01010105000482092d308209290201000282020100f601be0dccd04aa40b12f3f191ae17c1f9c8c0b68e7a77e14be25c3c7907cb1d33a6ef418ef41852f32c98392bc5c9aed91c1a1501c503eab89b3ee6f4f8eb2e0fcfc41bd03609cf6a8eb3aa6f0fbe23187b33db4d34b66d128a8aba0a2abf40bb9d13d8e2554569a57ab1d8c61b8cad2dc88599ae0da5346e15dace1bac7bf69737c22f083be9b46bb8b1eab5957b2da740275e96c87195b96fe11452159dafcfd916cee5d749a77bc3905a5ebd387ae445e8fe70f16e9a086639779ceffbfd41557bd99aea6a371a6b4b160615a1a12bc6958d34bce0c85adcbd8392fa10ceca52209d56196ba3d273ce228f1f111192aa92de2a039798a17bcecb4dc6100e6f8ae8c2643f2ae768b2255f082c978e95ca551555f10608231cf8003bbf807969fff1e51914b9a8c9b8f4564645b9e5d705ffad29663f5dae3d76652b422e43f13e6c1491090805c2d1268a74a251177427e33a9a91175c3670b91746008bce1fd231e6e4f2ad70cb43aca5f07600a6d31dd02915243dfdd943a02165da367a6b7e4dae1dd2e8b836903080795d2585076cc1c15dd9e8d2e5e047526569b1bfd395d957eb9fde325d342d14426e71efdc1887515e53cdea5834921f928629e748eed097ac4024e2bf255d70411f87373948cf8e8aa7effa2b0ab47d5166091e1aedec60568b155bd9c27bc55f3ece35f83d636dbcd5abf4853a051db94d5045020301000102820200065028224431ca35e87f82d97302c9384b4d341385ecd8510f4df94e51facf0dbfa01694139e3f00e34859db09bd087e74b2e1c1229652e73df7e49c2fb2dd9cda7f5b49d81a32e9403e4b97b6eeebfdb6e89e7d8fbf27b95282fca9668e649c68297bf367bcdc21a86dfc22132a177e4591024b5dd49ad091775271fc9d7cb6e8cd8a5858f93f4cf280bf0c1b69d675e6f760ab443fa8ee8ddf89a2a85d46a52c367c27db6d1ec6435e52eb86c7e0ab02b05543865423cc4f25346f55e1db6675e69832e43a04ccc78af3abd68477ed37698ab7f61facbdbcdb32552de5e89d8342aa9f445b8afac81bfc5bc05981ea20b340e948f710f7b3ee85f18b5c3c5832f2336706c5e9c9bd8e43d202e73a0f62776df4b715975eddd31aa643b14145057b4995556de614c57b33297bda0e05a8b8882a29563bf21686ce34c3960f905de73911987eb696e07eac0a63857e2894c3b4629477ecbf1fc76eafbb2ce4a0f00f8cdb6fbd6169e399151460522cf5b365d9bbb9587d07dac8c438982adea9ff243a86bbdf128eaa0d3a88871d8cdf081854258a651ff4226ee9749b4a6add090c159ccea06b9a10804e5fe15120cc63a5972eab0e43980dedaff321fadeea3ca60c3ba1c2980bb597ea783b80ab6eba87feb5754fd1d65d7cad6f81cf52c1a6bfebf9a75e9a316cb364d8cf467d96370871df2ee66ee1c1694a02239583910282010100fc21b855c5ad4ca2b6970516406f71c6e79efc4126e6598772db1e082de6b0dddaaa2a2951f04148e86e0bde28213b7f600f987308301eacea134062bb0c3ddf628da9abf93ef1ce3e75b0953a484dbd3554bd5c0649933dd77e527563e90f05a8013fddac958c329378e94303b304be5f9df1fe5b043a7fdd94700a3f0b1cbbd0516b7cd94c57ca96d9fd2a8ca973991218cba33a1c23d810f7519d1f7702ab72affdb3f84a1b2a88116e4033bc4d0cfc7989c657e0fe94e964476ae58bae6b7876f36c09d32b1a63f8c47c94a74c92eedf75fc27cffe0f8452363e4bc8f7653f3cb55eaf693cec70d13c875de935a8b20439ab7e93f76981c5957fc5bb44d90282010100f9c7f748a505d23ecef9a85f8097c8cf7d7028ef6c90e22a336511582d2cc3636e34ead37204dbd22f142a3fb1d5f857b0310c7a433f51ae14d4608b01b43aa8c7ae67835f7fbe0b9d97948b39e9ba2d3a1687edb8b56ee70ff0536dab4d0551f71ed0daee9e412449f5f099bcc15e4ef0554dc79f87fec5a0dea717c7054392bf444613937401bbef3c22fbf7e738c58779b981609a1f9c11dd6f0bbe9996e2773459e4cef247b02a9fc21296ac57a5b10561824310cfbdecc90e06598370e3698713fdbe2528ec4ef3dccaae701eedc3e54ad6e7af4e68e3b39bd2e97ac9119936c647a503511cb283df984cfd7c07f0f56aa8ae3166948ef3f41b0859934d0282010100815486aab0a0896bf97f13e3eb1f7f5c49195b49cc3b6277412a3688798b18f46422df479cb941b3b54e25964a3d69b897bcc8355160e58b4af29f1745dd2cabb670f634b9c058e6b3514947f2c27de5ed424f73b1e1f1be4a188911a0333f3a6688658b3ee8e3265a512e4deacadc470ee304ebb5224123afb461984fe8524fe0b6b30d32a59f6ed2dc74a96bc7cbfd1bb44e58a7092235c5d6272e12a2c862cb8c8cf5d109aa4fb1c6472875a14460c1ed5207c4b22bc494c7947eb7ca63a8cafd31361d000ddf16a2d79f13dd9140d979149b488cbf44945a5b6aaf13221bf4491ebbb7fca27ca20e221f49c3c37b89fcf2dc0e2cb63f8f8a9b7a142250590282010100b61d84ff934a4e437b16ee1b4b9fdf4ae13370b5385bde7a5464a123c0343df575f9e128ef9df944230d39cc9cf5dc0edb28b7e740b69ef024c1bfee39fcd5340ffaea0010160c535dc0920e7cd81be533d00fa554a1fc4d3e02c461569f5e7ca787f1515edf45b196b759884de652c38d5934cf92524e807b4d3b590bc39bc417ee4885a761d28ddadce6c8fdb3b961d3e7fd48064df9340a967f8b79997438841f48579a476ddb55088c308f68f2b29d01c6597a5a7c8d066284f63e37a68c3879c32aa3836675fd0eb2719883a91944561e9dd7e8aa6bb17157f08c48f8e6fae5c3e5a2bb6b5d580eec6c97ddcd9be0a49ef283a7031ad7aba8d438df4e950282010022fb8e5fcd9b767104e71244db53058c18061e1b0d1f63b73e2d59a95e2a10cd87426a33da13c287cdef8136e5e47e93fb9b30ad92628a7b543f48eb011a86356ab3cb480f27e391b018ca187d97af3d82e31861ecafa663db78aa89c3bd468e6aadefb3a43f78bc00b8014c95db54e9d21a017e8f21f671545edde9a965ea32dfff45cda37fca1aa5132f6c8eed222bd01fed5a6e7d639580c5955777a86544c2c4c939bdb8b4c486dda53072861a0334359bdb3758475e49d90d0539944e78cfcfd8fff55bb31a1cebc65b28f51e790701b2f7912188984f034e6e96e1c5251e33fe38fb221bce7a90a86857c5f56b6ca77307c45d5290b1f088ade082b349";
string privateKeyPkcs8 = String.hex2string(key);
mixed state = Standards.PKCS.parse_private_key(privateKeyPkcs8);
string ret;
string ct = String.hex2string("e4b9d12b1519d15af3a10fef8ed37f918e998c56b7d89fad34cecd08ecb9ae9b3213f1e9686be7ea525882a5f28a594963b4c16ed9207210646d0d5cac26920f92edd61b262a39f0f9a9f889da6f583c6fce47a08b0fd575b4bbd33e64da0eb390703e341ae3c4392b39360a1a623b8701ad51801e63df43237df4e816f2a1e4312099f1070c528fc10803879321e99e76104b2440cb4ca788c2eeda15a673e418ff247f8556a2c5be47bc016fc6a2a6caf4080d6004f4d8d17dae33e23c8bb4046fd91ea85560f9d68949da790ea662e32c3c44538d4a8bd555338ddbf4009a9d8b2cb42337ab138b6841c0f1d34f585ecb9c8be41a037fd79c3db489909da1328a170a4d676d62359166ba641d4ab0e6d56f26903e41dd4307742d6e76c67b88ac2f835a9d5b45de31a5e4b479e76b82b08c184a67f2b917c2f76ba8ebfe98b0071eee383de77cb5b06050eb058a5194eb8170b000b47862bf40c1baacb0e4c58210284556aee1ba1006f25618bece2e9578fb73fd389914db94343b41c407c7778e49b3aa3062c92c63e83d79aac7c7f3d1334f197b8660432f29504c6f1477f9d00a3cf56b6bba97ffbcbb5c68cd60972982bdc910419ec69bcc1cde7cdb1516706e7a51fb23da821754fc2385ccbc85ced7c7a32b9a0fd7fa71b9829a86247d1a0942546b25109079a7be7b2bff81803cd96102cdeead406b2446077b6e00");
array err = catch { ret = state->decrypt(ct); };
if(ret)
write("%s\n", ret);
}
This issue is similar to CVE 2020-14967, which also allowed for the prepending of \0-bytes to the ciphertext (which resulted in a buffer overflow due to difference in the expected and real length of the ct).
Cheers, Josh