Dokumentáció - wolfi95/szgbizt2020-asdfgh GitHub Wiki

Számítógép biztonság házi feladat dokumentáció

A feladat egy olyan online áruházat elkészítése volt, amiben egyedi formátumú animált képeket lehet vásárolni. A szoftverrel szemben elvárás, hogy a CAFF (CrySyS Animated File Format) formátumot kell támogatnia. További elvárás, hogy a teljes rendszer tartalmazzon HTTP(S) protokollon elérhető távoli szolgáltatást, valamint az ahhoz tartozó webes klienst. A rendszerrel szemben támasztott követelmény, hogy a felhasználók belépés után képesek legyenek CAFF fájlt feltölteni, letölteni, a fájlok között keresni, illetve a fájlokhoz megjegyzést hozzáfűzni. A rendszerben kell hogy legyen adminisztrátor felhasználó, aki a felhasználók adatait láthatja, illetve az összes fájl adatait módosíthatja, törölheti. Az alábbi dokumentuba az elkészült rednzser leírása kerül, a biztonsághoz kapcsolódó funkciókra és kérdésekre fókuszálva.

Architektúra

A rendszer négy fő részből áll: A felhasználói webes felület REST Api-n kommunikál a szerverrel, mely egy SQL adatbázisban tárolja a szükséges adatokat, a szerver pedig egy DLL formájában használja a c++ nyelven íródott parsert.

Backend

A szerver .NET Core nyelven íródott, mely egy REST APIt ajánl ki és SQL adatbázisban tárolja a kívánt adatokat, illetve a fájlrendszeren a CAFF és CIFF fájlokat. A kliens és a szerver közötti kommunikáció biztonságos lebonyolítását a szerver HTTPS konfigurációja biztosítja. A gyakori támadások elleni védelem érdekében a Security Code Scan eszközt használtuk, mely segít kiszűrni az Injection, XSS, Kriptográfiai, stb. kódolási problémákat statikus kódelemzéssel. A következő támadások ellen gondoltuk végig külön a védekezés módjait:

  • Man in the middle / information disclosure: HTTPS használatával és modern REST API technológiák alkalmazásával a problém,a elkerülhető.
  • DOS/DDOS: Léteznek ugyan az alkalmazás kódjában implementálható technológiák melyekkel korlátozhatóak az api felé tett kérések, ám a mai web szerver alkalmazások már sokkal jobban kezelik az ilyne jellegű támadások elleni védekezést, mint amit kézzel készíteni tudnánk.
  • Cross Site Scripting: A .NEt core keretrendszer beépített megoldást nyújt erre a problémára, konfigurálható azoknak a weboldalaknak a listája, melyektől a szerver fogad kéréseket.
  • SQL Injection: A Linq keretrendszer automatikus védelmet ad a parancsbeszúrásos támadások ellen.
  • Path traversal: A biztonsági tesztelés során ez volt az egyetlen támadási mód melyre nem gondoltunk a fejlesztés előtt és az SCS tool híta fel rá a figyelmünket. A fájl elérés esetén a fájlműveleteket csak úgy szabad végezni, ha a felhasználó által szolgáltatott (pl.) fájlnév validálva lett. Szerencsére erre a problémára is létezik beépített validáló függvény.
  • Hamisítás/Megszemélyesítés: Bejelentkezés során JWT tokent használunk, melybe bele vannak téve a felhasználó adatai. Mivel a CPP modult DLL-ként használja a program, a memóriaterület egyezik a két program futásánál, így nem kell tartani hibás memória terület eléréstől.

CPP komponens

A külső komponens leírása itt található

Frontend

A kliens oldal Angular keretrendszerben lett megvalósítva, mely egy TypeScript alapú nyílt forráskódú keretrendszer, melyet a Google fejlesztett ki, illetve hosszútávú támogatottságát élvezi a cégnek. Egy Angular projekt komponensekből épül fel, a komponens logikája a TypeScript fájlban kerül megírásra, melyhez tartozik egy HTML template, illetve CSS stílusleíró fájl. A projektbe npm segítségével lehet behúzni a külső függőségeket. Az Angular keretrendszer beépített funkciókat kínál a biztonságos fejlesztéshez. Ezenfelül a következő lépéseket tettük meg a támadások elkerülése érdekében:

  • XSS elkerülése: Az Angular keretrendszer beépített támogatást nyújt ennek elkerülése érdekében: {{}} string interpolációt használunk a sablonokban, mely segít a potenciálisan veszélyes karakterek biztonságos kódolásában és a megbízhatatlan HTML, CSS kifejezéseket megakadályozza. A keretrendszer alapértelmezetten az összes adatot megbízhatatlannak tekinti, így az összes könyvtár úgy van megírva, hogy ezt a bevált gyakorlatot követi.
  • [innerHTML] tag használata: Amikor dinamikusan adunk hozzá HTML tartalmat egy komponenshez, akkor annak generálásánál az [innerHTML] jelzőt használjuk. Ez biztosítja, hogy a rendszer az adatokat HTML-ként értelmezi, és megtisztítja, eltávolítja a nem biztonságos tageket, így megakadályozva, hogy bármilyen rosszindulatú script beleavatkozzon a helyes működésbe.
  • Nem használunk olyan templatet, aminek kódja felhasználótól érkező inputtal való konkatanációból generálódik.
  • Nem használunk natív DOM API-kat ahhoz, hogy interakcióba lépjünk az oldal HTML elemeivel. Ehelyett van az Angular template mechanizmusa, illetve az Angular nyújt ehhez saját API-kat.
  • Mivel az Angular projektekbe egyszerűen beimportálhatunk open-source komponenseket, így ezek használatára különösen kell figyelni, hogy megbízható forrásból származzanak. Ilyen a projektben a file-saver.js külső könyvtár.
  • A frontend projektre npm audit fix lett futtatva, mely megvizsgálja az alkalmazás függőségei okozta biztonsági réseket, illetve automatikusan telepíti a kompatibilis frissítéseket a sérülékeny függőségekre.
  • Hamisítás/Megszemélyesítés elkerülése: A bejelentkezéshez JWT tokent használunk. Mivel ebben felhasználói adatok vannak, így nagyon meg kell gondolni, hogy hol tároljuk el a tokeneket, hiszen kiemelt fontosságú védni őket a CSRF és XSRF támadások ellen. Olyan helyen kell tárolni a tokeneket, ahol a támadók nem tudják elérni. Két lehetséges megoldás van ezek biztonságos tárolására:
  1. Local storage: Nem sebezhető CSRF támadásokkal. Esetünkben local storageban van tárolva a token.
  2. HTTPOnlyCookie: Ezek nem elérhetők a kliens oldalról, a kliens nem tudja elolvasni tartalmát

Tesztelés

A alkalmazás frontend részének unit teszteléséhez Jasmin test keretrendszert, a tesztek futtatásához pedig a Karma tesztfuttató került felhasználásra. Ezekkel dolgozni kifejezetten egyszerű, mivel a legenerált applikáció ezeket a függőségeket már alapból tartalmazta.

  • Jasmine
    A Jasmine egy viselkedés-vezérelt (BDD) keretrendszer JavaScript kód teszteléséhez. A tesztek előnye, hogy kifejezetten olvashatóak és értelmezhetőek is a fejlesztők és laikusok számára egyaránt.

  • Karma A Karma egy automatizált tesztfuttató , mely nagyban megkönnyiti a fejlesztők számára a tesztfuttatást azáltal, hogy nem szükséges segitségével a tesztek manuális egyenkénti elinditása. Egy böngészőablak megnyitása segitségével abban hajtja végre az egyes tesztekben leirtakat.

Példa teszt

describe('CafffileCreateComponent', () => {
  let component: CafffileCreateComponent;
  let fixture: ComponentFixture<CafffileCreateComponent>;

  const caffFileServiceMock = {
    uploadCaffFile: () => of,
  };

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [CafffileCreateComponent],
      imports: [ReactiveFormsModule],
      providers: [
        {
          provide: CafffileService,
          useValue: caffFileServiceMock,
        },
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(CafffileCreateComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should call upload function with valid form', () => {
    spyOn(caffFileServiceMock, 'uploadCaffFile').and.callThrough();
    component.uploadForm.setValue({
      name: 'caff image name',
      file: '',
    });
    let input = fixture.nativeElement.querySelector('input[type=file]');
    const dataTransfer = new DataTransfer();
    dataTransfer.items.add(new File(['content'], 'caffFile'));
    input.files = dataTransfer.files;
    input.dispatchEvent(new Event('change'));
    input.dispatchEvent(new Event('input'));
    fixture.nativeElement.querySelector('button').click();
    expect(caffFileServiceMock.uploadCaffFile).toHaveBeenCalled();
  });

Egy teszt felépitesét a fenti kódrészlet szemlélteti.

  • a describe-bal irjuk le az egyes Test Suite-okoat, ebben az esetben a CAFF file feltöltéséhez tartozó test suite látható
  • beforeEach ezek a függvények minden test case előtt lefutnak, hogy a tesztesetek ne befolyásolhassák egymást, a függvényben létrehozott objektumok módositása által
  • ay it az egyes Test Spec-eket irja le ezek a tesztesetek, test case-k, ezek tartalmaznak egy vagy több elvárást a teszt kimenetelével szemben
  • expect(something) részben az előbb emlitett elvárás látható. Ebben a példában az, hogy ay adott függvény, mely a CAFF file-ok feltöltéséért fellelős meghivódjon, hisz minden adott hozzá.
  • caffFileServiceMock, a tesztelt komponens mint általában minden komponens függőségben áll más komponensekkel, de hogy ezeket elszigeteljük egzmástól, és egyszerre csak egynek a tesztelésével tudjunk foglalkozni egy mock-t készitünk a szükséges egyéb komponensekből, és a megvalóstjuk azok azon metódusait melyre a tesztjeinkhez szükség van, jelen esetben ez a CaffFileService, mely uplodaCaffFile függvénye a lehető legegyszerűbb módon megvalósitásra is került.

A fenti teszt suite tehát egyetlen test case-e a file-k feltöltésének működését teszteli, ad neki egy nevet illetve feltölt egy itt létrehozott file-e, ezzel jelképezve a feltölthető CAFF filet-t, majd rákattint a from egyetlen, feltöltés gombjára és ellenőrzi, hogy az elvártnak megfelelő esemény történt-e, meghivásra került-e az upload függvény. Ha minden rendben volt a teszt lefutása sikeres.

Az alkalmazás további tesztjei is ezem a sémán alapulnak.