DOMANDA Sicurezza Programmi

davicos

Utente Attivo
226
11
Salve a tutti,
la mia domanda è un pò generale e spero di essere nella sezione corretta dato che è una domanda sulla sicurezza informatica ma precisamente sulla programmazione.

Tenendo presente che un programma complesso, come un sistema operativo o un antivirus, richiede il lavoro di diverse persone, risulta inevitabile il rischio di commettere errori che posso essere fatali per esempio su programmi di gestione finanziaria, etc. Insomma ci posso essere delle brecce in grado di bypassare tutta la sicurezza presente nel programma.

Ora, tenendo presente questo semplice programma:

C++:
#include <iostream>

using namespace std;

int const password = 3;   // password può anche essere una stringa di numerosi caratteri più o meno complessi
                          // per semplicità ho inserito una sola cifra, ma il concetto è chiaro
int codice;

int main()
{



    while (codice != password)
    {
        cout << "Immettere codice: " << endl;
        cin >> codice;
        if (codice != password)
        {
            cout << "Codice errato, riprovare" << endl;
        }
        else
        {
            cout << "Codice corretto" << endl;
        }

    }


    return 0;
}


è possibile trovare una breccia per estrapolare la password senza necessità di programmi basati sulla brute force?
Non sono tanto interessato alla esatta procedura ma sono curioso di sapere con quali mezzi si potrebbe riuscire a trovare tale password, per quali vie traverse.
All'apparenza, essendo un programma lineare e senza problemi di conflitto tra qualche riga di codice a qualche altra situata magari in una classe lontana lontana, il programma potrebbe risultare impenetrabile. Immagino però non sia così.

Grazie.
 

Sysken

Nuovo Utente
51
20
Onestamente io non penso che il problema sia tanto l'immissione della parola chiave, bensì la sua memorizzazione. Ovviamente ambe due gli aspetti hanno la stessa importanza.
Per farti un esempio, prendiamo un semplicissimo sito in cui è necessario loggarsi per usufruire dei servizi che offre. Al momento della registrazione la tua parola chiave verrà salvata in un DB ma non prima che questa venga criptata in SHA256 MD5 o altri: In questo caso l'unico modo per trovare la parola chiave è quella di "intercettarla" all'immissione e questo è un tipo di attacco detto MITM (Man in the middle), facilissimo da applicare a siti che utilizzano il protocollo http e non quello https (HTTP + TLS).
Nel tuo caso un modo relativamente semplice per scovare la parola chiave è quello di analizzare il frame fisico in cui lavora il processo e individuare tutte le variabili.
 

davicos

Utente Attivo
226
11
Quindi anziché bypassare le righe del codice si bypassa direttamente il programma usando l sistema operativo come complice?
 

Sysken

Nuovo Utente
51
20
Cosa intendi per bypassare? Il calcolatore è un "servo obbediente" fa esattamente ciò che gli hai richiesto quindi al massimo potresti fargli eseguire del codice "maligno".
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
E' molto vario come discorso. Dice bene Sysken, quando asserisce che il problema sia la memorizzazione della password.

Solitamente quando si cifra una password lo si fa con un algoritmo conosciuto. Nel caso delle password di un utente che si logga su un sito, tipicamente si utilizza un hash. Ma più in generale, ad esempio nel caso di un software che memorizza password come in un archivio per consetire all'utente la sua gestione, si possono utilizzare altri algoritmi (come RSA, tanto per citarne uno).
Qui si aprono numerosi temi: innanzitutto, se l'algoritmo è solido, non è un problema se è conosciuto. Viceversa, ci può essere un algoritmo sconosciuto e totalmente insicuro (magari si risale alle utilizzando proprio la matematica, cosa che, tornando ad RSA, risulta più complessa).
Tutto ciò conduce all'implementazione specifica.

Arrivando al software: questo fa la differenza. Per assurdo, potrebbe essere utilizzato un algoritmo conosciuto e inviolabile (ripeto, per assurdo), ma con una semplice patch (altresì noto come "crack") bypassare il controllo.
Il tuo codice di esempio ricade proprio in questo caso. Aggiungendo un bel JMP (JUMP) nel programma compilato, un salto incondizionato, è possibile saltare sempre a "il codice è corretto"; immagina ora che dopo questo messaggio si abbia accesso alle password in chiaro, o a qualsiasi altro dato sensibile... la sicurezza sarebbe già compromessa (esegui a tal proposito es_patch1.exe; ho alterato solo il controllo, per mostrarti un esempio).
Anche qui, ci sono svariati modi per intervenire (modificando la locazione di memoria della variabile, o patchando i controlli che la riguardano e tanti altri ancora).

Il tuo è solo un codice brevissimo ed esemplificativo, certo, ma il presupposto è sempre quello che "da qualche parte il controllo lo si deve fare". Purtroppo non è semplicissimo nasconderlo bene, ed è qui che si ricorre ad offuscatori del codice e chi più ne ha più ne metta, per rendere il codice (decompilato) quanto più incomprensibile (ci sono anche protezioni che eseguono una vera e propria emulazione... ma non vorrei andare troppo OT).
Tra questi casi puoi considerare anche la validazione di un seriale per un qualche prodotto. In questo caso ci sono N seriali validi, e vengono calcolati dal software secondo un certo algoritmo che verifica magari determinati pattern (ci sono soluzioni di tutti i tipi, queto è solo un esempio).


Ovviamente, nel caso di un applicazione Web, cambia tutto: un classico software web, con architettura client/server, magari client in HTML e server in PHP/Node, Java... avrebbe problemi differenti (il codice che si occupa della cifratura, non è accessibile, ma si trova tipicamente su un server remoto). Quindi valgono solo le considerazioni sopra esposte, ma unicamente in relazione alla cifratura.
 

Allegati

  • es_patch1.zip
    16.7 KB · Visualizzazioni: 30
  • Mi piace
Reazioni: Sysken

pabloski

Utente Èlite
2,868
916
All'apparenza, essendo un programma lineare e senza problemi di conflitto tra qualche riga di codice a qualche altra situata magari in una classe lontana lontana, il programma potrebbe risultare impenetrabile. Immagino però non sia così.

Lineare? Provato ad inserire una stringa al posto di un numero? Nota che succede. Benvenuto nel mondo dei DOS ( non il sistema operativo ma il denial of service ).

Questo per sottolineare un punto, ovvero che il rapporto tra sorgente ed eseguibile non è 1:1. Quel programma semplice in realtà contiene una sequenza di istruzioni del runtime del linguaggio. Altre istruzioni prese dalla libreria standard del linguaggio. Gli stream C++ sono bestie estremamente complesse.

A ciò devi aggiungerci ovviamente le syscall al sistema operativo, altrimenti l'input e l'output te li scordi. E lì possibilità di buchi se ne aprono parecchie.

Infine, parlando nello specifico di C e C++ ( ma vale anche per altri linguaggi anche se in misura diversa ), ci sono tutta una serie di bug introdotti dagli stessi compilatori. Bug dovuti a comportamenti non definiti nei relativi standard dei linguaggi, alle ottimizzazioni troppo aggressive, ecc...

In generale i bug si trovano partendo dal punto più ovvio, ossia gli input. In fondo se vuoi sovvertire il funzionamento di un programma quale altro strumento hai se non gli input? Un programma che non s'interfaccia col mondo esterno è ovviamente inattaccabile. Ok ci sarebbero cose come i bit flip dovuti alla fisica dei microcircuiti, ma ovviamente non vengono classificati come bug del software.
 

Giacomo Furlan

Utente Attivo
351
87
CPU
AMD Ryzen 5900x
Dissipatore
BeQuiet! SilentLoop 2 360mm
Scheda Madre
Gigabyte X470 AORUS Gaming 7 WIFI AMD X470
HDD
Crucial P5 Plus 2 TB PCIe M.2 2280SS
RAM
Patriot Viper Steel RAM DDR4 3600 Mhz 64GB (2x32GB) C18
GPU
MSI GeForce RTX 2080 Gaming X Trio
Audio
SteelSeries Arctis 9
Monitor
Alienware AW3423DWF
PSU
EVGA SuperNOVA 650 G3, 80 Plus GOLD 650W
Case
Sharkoon TG5
OS
Windows 11, Fedora 36
Quel programma lì te lo cracko con un editor esadecimale... ti basta infatti modificare un singolo salto.

Nelle applicazioni eseguite localmente l'attacco più facile è quello appunto del cracking, più che del brute force. Esistono sistemi anti-tampering (come DENUVO per i videogiochi, tanto per citarne uno conosciuto) più o meno complessi che si assicurano che il codice eseguito sia originale (già, non è una protezione ai diritti d'autore... lo è indirettamente), i quali potrebbero far desistere (più o meno fortemente) ogni prova di manomissione.

Nelle applicazioni client / server, dove le password sono gestite remotamente e specialmente dove i dati richiesti non sono locali, allora gli attacchi si spostano più su un discorso di SQL injection (provo ad eseguire linguaggio SQL in modo illecito tramite un bug dell'interfaccia del server), hacking dei server di database e così via. Se quindi anche una persona riuscisse ad entrare nel server dove ospiti i dati sensibili (password, carte di credito etc), allora subentra un secondo livello di sicurezza: crittazione o hashing dei contenuti. La differenza sostanziale tra i due metodi è che il primo può essere decodificato, il secondo no. Ma anche in questi casi puoi utilizzare algoritmi più o meno potenti con chiavi più o meno forti (non solo in lunghezza, ma anche da come vengono generate).

Il discorso è tanto complesso che ci vorrebbe un'intero corso di specializzazione per spippolarti il tutto :P
 

pabloski

Utente Èlite
2,868
916
Lineare per dire che nel programma non sono state usate classi o simili.

Esattamente. Il problema è che quello che vede il programmatore non è necessariamente quello che vede la macchina. Lessi un articolo tempo fa molto interessante a questo proposito, in cui si faceva notare come un programma sorgente perfettamente corretto veniva trasformato dal compilatore in un programma buggato.

Inutile dire che questa è la ragione per cui si dice che i bravi programmatori scrivono codice, ma i guru conoscono per filo e per segno come i compilatori trasformano quel codice. In sostanza per scrivere software efficiente e corretto non basta conoscere i comandi di un linguaggio.
Post unito automaticamente:

Quel programma lì te lo cracko con un editor esadecimale... ti basta infatti modificare un singolo salto.

Nelle applicazioni eseguite localmente l'attacco più facile è quello appunto del cracking, più che del brute force.

Un programma su cui puoi mettere le mani è spacciato in ogni caso. In generale ha senso pensare alla sicurezza nei termini di un attacco esterno contro un software che riguarda i suoi dati. Se l'attaccante ha la possibilità di modificare il codice macchina, solo la crittografia ti può salvare.
 
  • Mi piace
Reazioni: Andretti60

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!