본문 바로가기
Backend/NestJS

main.ts 파해치기 (useGlobalPipes 옵션 whitelist)

by 찬찬2 2024. 6. 28.

우선 whitelist 옵션이 무엇인지 알아보기 전에 whitelit 옵션이 없을때 어떤 일이 일어나는지 보자.

 

만약 사용자가 students 테이블에서 점수가 50 점 이상인 학색들 정보를 받아온다고 했을때, 사용자는 아래와 같이 서버에 요청할 것이다.


URL :호스트/students?score=50

Method: GET

 

// controller.ts
@Controller('students')
export class StudentsController {

   @Get()
   getAllStudents(
      @Query() query: StudentsDto
   ){
      return this.studentsService.getAllStudents();
   }
}

// service.ts
@Injectable()
export class StudentsService {
   constructor(
      @InjectRepository() 
      private readonly studentsRepository: Repository<StudentsModel>
   ){}
   
   async getAllStudents(dto: StudentsDto){
      return await this.studentsRepository.find({
         where: dto // dto 는 score 정보만 가지고 있다.
      });
   }
}

// entity.ts
@Entity()
export class StudentsModel {
   @PrimaryGeneratedColumn()
   id: number;
   
   @Column()
   name: string;
   
   @Column()
   class: number;
   
   @UpdateDateColumn()
   updatedAt: Date;

   @CreateDateColumn()
   createdAt: Date;
}


// dto.ts
export class StudentsDto {
   @IsNumber()
   score: number;
   
   @IsString()
   @IsOptional()
   name?: string;
   
   @IsNumber()
   @IsOptional()
   class?: number
}


// 결과
// [{
//    "id" : 1,
//    "name" : "chanki",
//    "class" : "A"
//    "updatedAt" : "2024-06-24T16:27:32.564Z",
//    "createdAt" : "2024-06-24T16:27:32.564Z"
// }]

 

사용자의 요청은 위 코드들에 의해 점수가 50점인 학생들을 students 테이블에서 가져와 응답할 것이다.

 

만약에, 사용자가 실수로든 악의적으로든 "id=2" 를 더 붙혀서 보낸다면 어떻게 될까?

 

StudentsDto 에는 보다시피 id 프로퍼티가 정의되어 있지 않다. 그런데 결과는!!

 

id=2 조건을 받아들여 테이블에서 조회까지 하게되버린다. 만약 악의적인 사용자였다면 특정 학생정보를 찾아 그 정보를 악용할 수 있을 것이다.

 

사용자가 요청한 쿼리 "id" 는 설계된 DTO  프로퍼티에 포함되어있지 않기때문에 설령 사용자가 보냈더라도 서버는 이를 읽고 처리하면 안된다.

 

whitelist: true 는 정의되지 않은 프로퍼티를 pipe 단계에서 stripped(=벗겨 낸다) 한 뒤 controller 에 전달하는 것이다. 해당 옵션을 설정하면 id=2 는 controller.ts 에서 읽히지 않게 된다.

 

그리고 추가적으로, forbidNonWhitelisted: true 를 설정하면 에러를 반환하게된다.

 

// app.module.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

function bootstrap() {
   const app = await NestFactory.create(AppModule);
   app.useGlobalPipes(new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true
   });
}

 

댓글