博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Have you ever played with Domino?
阅读量:5884 次
发布时间:2019-06-19

本文共 8666 字,大约阅读时间需要 28 分钟。

hot3.png

IBM Lotus Domino is an email client rather common in companies like Microsoft Outlook. This article proposes to observe a small part of the application engine, namely one method used to store the user's password. In a second step, we will conduct a brief analysis of all used algorithms then we will see how to implement a plugin for John The Ripper to bruteforce discovered digests.

Introduction

This article deals with Lotus Domino reverse engineering, especially the user authentication process when a mailbox is accessed. How password digest are stored? Which cryptographic algorithms are used? How? We will end up with a bruteforce implementation using John The Ripper.

We have used the 8.5 version during our analysis and it's probable that following analysis is valid for further or previous versions. We will also consider the Domino server has a classical configuration.

Password's hash storage

Password hashes are stored inside the well known user.id file, generated by the Lotus Domino server and stored on client file system, usually in%USERPROFILE%\AppData\Local\Lotus\Notes\Data. The interesting part is located at offset 0xD6 where the ciphered user password digest is stored:

static/resources/2013-12-19_domino_password_cracking/images/user_ciphered_blob.png

Note that the blob size could vary and we still have to figure out why. It is stored as a unsigned short (16 bits) at offset 0xD6 and starting from offset0xD8 ciphered data can be found.

To summarize, this file contains all information about user's profile:

  • Username and organization info (CN, O,...) ;
  • Language ;
  • Lotus Domino server address ;
  • User's certificate and password digest ;
  • And many other things that should be reversed...

The file format is not documented but with a bit of reverse engineering, we can put in the spot that nnotes.dll is in charge of parsing this file and executing different kind of cryptographic algorithms.

The mail client has to check user's credentials before he can access its mailbox. Credentials are not directly stored as a raw digest but they are ciphered using an unique key per user. Used algorithms are well known (like RC2 or SHA-1) however the global process is custom and a bit scrambled.

static/resources/2013-12-19_domino_password_cracking/images/domino_pass_storage.png

The biggest surprise comes from the final digest bytes count, 5 bytes only or 40 bits. Quite surprising especially as we will see later that the SHA-1algorithm is used for the key derivation process.

The last 5 bytes are generated with this algorithm:

void compute_msg_mac(uint8_t *msg,size_t len,uint8_t *msg_mac) {
size_t i,j; uint8_t c; for(i=j=0;i

Why not directly using the classical SHA-1 + Salt? NSA again? Maybe too easy. However, many years ago, we know that the agency inserted a backdoor which stored some key (the one used when sending email) bits using asymmetric cryptography, so they could decipher any messages later with a little bruteforce.

Lotus Domino key derivation

One thing is still missing, how the RC2 key is derived from user's password? Here is the global scheme, a custom 128 bits hash function is used and also a new kind of hash/checksum algorithm based on few trivial XOR operations:

static/resources/2013-12-19_domino_password_cracking/images/domino_pass_derivation.png

The new checksum algorithm can be implemented as below:

void compute_key_mac(uint8_t *data,size_t len,uint8_t *mac,size_t mac_len) {
size_t i,j,mlen=mac_len-1; uint8_t k; for(i=0;i<16;i++) {
k = ebits_to_num[mac[0] ^ mac[1]]; for(j=0;j

The ebits_to_num array can be found in openssl source code inside tab.c of RC2 package:

unsigned char ebits_to_num[256]= {
0xbd,0x56,0xea,0xf2,0xa2,0xf1,0xac,0x2a,0xb0,0x93,0xd1,0x9c,0x1b,0x33,0xfd,0xd0, 0x30,0x04,0xb6,0xdc,0x7d,0xdf,0x32,0x4b,0xf7,0xcb,0x45,0x9b,0x31,0xbb,0x21,0x5a, 0x41,0x9f,0xe1,0xd9,0x4a,0x4d,0x9e,0xda,0xa0,0x68,0x2c,0xc3,0x27,0x5f,0x80,0x36, 0x3e,0xee,0xfb,0x95,0x1a,0xfe,0xce,0xa8,0x34,0xa9,0x13,0xf0,0xa6,0x3f,0xd8,0x0c, 0x78,0x24,0xaf,0x23,0x52,0xc1,0x67,0x17,0xf5,0x66,0x90,0xe7,0xe8,0x07,0xb8,0x60, 0x48,0xe6,0x1e,0x53,0xf3,0x92,0xa4,0x72,0x8c,0x08,0x15,0x6e,0x86,0x00,0x84,0xfa, 0xf4,0x7f,0x8a,0x42,0x19,0xf6,0xdb,0xcd,0x14,0x8d,0x50,0x12,0xba,0x3c,0x06,0x4e, 0xec,0xb3,0x35,0x11,0xa1,0x88,0x8e,0x2b,0x94,0x99,0xb7,0x71,0x74,0xd3,0xe4,0xbf, 0x3a,0xde,0x96,0x0e,0xbc,0x0a,0xed,0x77,0xfc,0x37,0x6b,0x03,0x79,0x89,0x62,0xc6, 0xd7,0xc0,0xd2,0x7c,0x6a,0x8b,0x22,0xa3,0x5b,0x05,0x5d,0x02,0x75,0xd5,0x61,0xe3, 0x18,0x8f,0x55,0x51,0xad,0x1f,0x0b,0x5e,0x85,0xe5,0xc2,0x57,0x63,0xca,0x3d,0x6c, 0xb4,0xc5,0xcc,0x70,0xb2,0x91,0x59,0x0d,0x47,0x20,0xc8,0x4f,0x58,0xe0,0x01,0xe2, 0x16,0x38,0xc4,0x6f,0x3b,0x0f,0x65,0x46,0xbe,0x7e,0x2d,0x7b,0x82,0xf9,0x40,0xb5, 0x1d,0x73,0xf8,0xeb,0x26,0xc7,0x87,0x97,0x25,0x54,0xb1,0x28,0xaa,0x98,0x9d,0xa5, 0x64,0x6d,0x7a,0xd4,0x10,0x81,0x44,0xef,0x49,0xd6,0xae,0x2e,0xdd,0x76,0x5c,0x2f, 0xa7,0x1c,0xc9,0x09,0x69,0x9a,0x83,0xcf,0x29,0x39,0xb9,0xe9,0x4c,0xff,0x43,0xab, };

This array has been used for years in custom algorithms / cryptographic schemes implemented by IBM inside Lotus Notes, especially for user authentication.

At the end, a 64 bits key is produced and it can be directly used to decipher the user's blob stored in user.id file.

Credential check

To summarize, the scheme seems to be a bit confused and uncommon compared to many applications. In fact, the password is only used to derive a key when it is stored and the check is made against data stored in the user blob deciphered using this secret key.

Last 5 bytes of the deciphered blob could be considered as final password hash and all previous bytes checksum / hash should be equal to it. Thus, it reduces the overall security to almost 40 bits. Another solution to break the system could be to directly attack the RC2 64 bits key using bruteforce techniques, which is not so unrealistic considering modern equipment or cloud computing.

However, we will try to bruteforce the whole algorithm to retrieve the plaintext password. That's why we decided to implement a JTR plugin.

John The Ripper plugin

Now we know how to decipher user id blob and how to produce the same kind of digest from plaintext password, it is easy to write a John The Ripper plugin and benefit of its efficient bruteforce engine.

Writing a plugin for JTR is an easy process and we just have to write a C file, with a new fmt_main structure declaration (also defined in formats.h).

This structure is automatically registered once (and the associated code is generated by the Makefile) in the JTR engine and describe how the plugin should be used:

  • digest size, salt size, plaintext size ;
  • digest comparison ;
  • many callbacks to prepare, compute a digest from given plaintext passwords ;
  • hash table prototype to improve performances.

You can download the plugin  , just store it in src folder and compile. The code is really not optimized but as the algorithm is overall easy and consists in few XOR operations, performances are not so bad and you can expect more than 100000 tries / second (e.g with a standard Core i7 2.8Ghz). It can be really improved by using parallel programming techniques with OpenMP for example.

The first thing to do is extracting the ciphered blob from the user.id file, you can use this tool LotusIdHashExtractor available  It just extracts the ciphered blob as a hexadecimal string that can be used with the JTR plugin.

Here is sample execution trace:

./john --wordlist=big_dict.txt  --format=lotus85 domino.dump Loaded 1 password hash (Lotus Notes/Domino 8.5 [8/64]) guesses: 0  time: 0:00:00:06 0.06%  c/s: 75779  trying: DEWMUGUO4L - W7BTKCT9Y8 guesses: 0  time: 0:00:19:20 10.22% c/s: 66970  trying: TjAPKs7EGT - fXd0AackHq guesses: 0  time: 0:00:34:52 18.70% c/s: 72320  trying: fzFp4whj - xZHGk8lc lanetrotro         (?) guesses: 1  time: 0:00:54:40 DONE (Tue Dec 17 23:27:10 2013)  c/s: 74491  trying: lanetrot11 - lanetrotze

This bruteforcer could be used in forensic investigations or while pentesting. Note that all tools are experimental and could not work in some situation, maybe depending on server configuration, used versions used or other parameters.

Conclusion

Here we just have made a minimalist analysis of the algorithm and there are still other things to check like the source of the user blob, are those bytes generated from user profile data or using a PRNG? Is the PRNG secure? Some new reverse engineering sessions should be started...

Finally, this analysis is just a little part of all things that are possible to do with this quite complex application. It could be interesting now to check how emails are ciphered, maybe still with this famous 64 bits key? And what about email parsing?

There are still many things to dig into.

Acknowledgments

  • Kevin Szkudlapski
  • Solar Designer for its excellent John The Ripper
  • All pony lovers :)

Update

Add licence for lotus85_fmt_plug.c

转载于:https://my.oschina.net/u/1188877/blog/292367

你可能感兴趣的文章
高性能 Oracle JDBC 编程
查看>>
java 中ResultSet可以获取的数据类型及返回值类型列表
查看>>
ubuntu 13 安装SH程序
查看>>
如何用几个简单的命令改善你的Linux安全
查看>>
查看MySQL记录执行过的SQL
查看>>
SpringMVC 之 国际化
查看>>
【转】Java并发编程73道面试题及答案
查看>>
你流量大吗?check_traffic.sh监控服务器流量
查看>>
java8 时间类与Date类的相互转化
查看>>
下半年过了中项,感谢学院,感谢薛老师,后面就跟着学院的各位老师学与考了
查看>>
RAID磁盘冗余阵列
查看>>
支付宝升级延时到账功能
查看>>
ghost后只剩下一个盘的数据寻回方法
查看>>
输入输出练习
查看>>
Git commit message和工作流规范
查看>>
java面试。答案源于网上
查看>>
yii中取得CActiveDataProvider的分页信息
查看>>
我的大学
查看>>
Google翻译接口收费啦
查看>>
Debian+Apache2服务器
查看>>