보안에 대해 바보 같은 짓은 그만합시다.

나는 러시아인, 중국인 또는 스파이가 관련된 장대한 해킹으로 보고된 내용을 접했을 때 해킹 피해자가 어떤 형태의 기본 보안도 심각하게 받아들이지 않았다는 사실이 밝혀지는 것을 싫어합니다. 그것은 Bonnie와 Clyde에게 금고 밖의 큰 배너에 콤보가 인쇄되어 있고 안전 금고의 열쇠가 없는 은행을 털도록 요청하는 것과 같습니다. 또는 여우를 암탉 집 안으로 들여보내는 것과 같습니다.

불행히도 이 사건의 피해자는 미국 정부인 것 같습니다. 기사 제목: "How the Russians penetrated Illinois election computers - ABC7 Chicago" .

해킹은 무엇이었습니까? SQL 인젝션. SQL 주입!!@!@!! #$%@ 무엇? 우리는 90년대에 살고 있습니까? 개발자들은 대체 무엇을 하고 있는 걸까요? 슬프게도 지난 1년 동안 작업한 프로젝트에서 문제가 발생했습니다. WTF는 사람들에게 잘못입니까? 우리는 게으르거나 멍청하거나 둘 중 하나입니까?

SQL 인젝션에 대해 알려드리겠습니다.



다음은 무고한 쿼리입니다. Postgres와 NodeJS를 사용한다고 가정해 보겠습니다.

SELECT firstName, lastName, email From users where email = "[email protected]"

나쁘지는 않지만 Javascript로 어떻게 빌드할 수 있는지 봅시다.

async function lookupUserByEmail(emailAddress) {
    if(!emailAddress) {
        throw "Email address is required!";
    }

  return await db.any(`SELECT firstName, lastName, email From users where email = "${emailAddress}"`)
}

이메일이 있는지 확인하고 데이터베이스에서 사용자 기록을 가져오는 간단한 방법이 있습니다. 문제는 문자열 보간을 수행하고 있다는 것입니다. 즉, 해당 쿼리를 가져와 emailAddress 변수에서 ANYTHING을 삽입합니다. 별거 아니지?

이메일 주소가 다음과 같다면 어떻게 될까요?

1 OR 1=1; 

즉, 아무 것도 일치하지 않는 첫 번째 값인 1 또는 1=1과 같이 SQL에 의해 문자 그대로 해석되는 1=1에 일치한다는 것을 의미합니다. 항상 사실입니다. 따라서 시스템의 모든 레코드를 반환합니다.

누군가 SQL Injection을 사용하여 해를 끼칠 수 있습니까?



해커가 시스템에 대한 지식이 없고 다음을 수행한다고 가정합니다.

1 or 1=1;

이제 테이블의 모든 레코드 목록이 있습니다. 좋습니다. 시스템에 어떤 옵션이 있는지 알고 싶다면 어떻게 해야 합니까? 자, 이렇게 하세요:

1'; SELECT c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN (‘r’,”) AND n.nspname NOT IN (‘pg_catalog’, ‘pg_toast’) AND pg_catalog.pg_table_is_visible(c.oid); 

버전?

1'; SELECT version();

포스트그레스 사용자?

1'; SELECT usename FROM pg_user;

사용자 및 암호 해시? 괜찮아요:

1'; SELECT usename, passwd FROM pg_shadow — priv;

입력 내용을 삭제하지 않으면 쉽게 해킹할 수 있는 경우가 많습니다. 사실 many , dozensdifferent guidesanyall versionsSQL .

나 자신을 어떻게 보호합니까?



시카고의 바보들과 달리 값비싼 Cisco 방화벽을 사는 것은 당신을 보호하는 데 아무 소용이 없습니다. 사실, 그것은 당신이 더 안전하다고 느끼게 할 뿐이므로 더 많은 위험을 감수해야 합니다. 아니요, 당신에게 필요한 것은 진정한 보안입니다. 기본 보안. 그것은 보안의 문 유형에 자물쇠를 두는 것과 같습니다.

매개변수화된 쿼리(일명 "준비된 명령문" 입력)



거의 모든 SQL 라이브러리가 매개변수화된 쿼리를 지원합니다. 그렇지 않은 경우 사용할 새 라이브러리를 찾아야 합니다.

PQ의 예:

위의 예에서 안전한 쿼리는 다음과 같습니다.

async function lookupUserByEmail(emailAddress) {
    if(!emailAddress) {
        throw "Email address is required!";
    }

  return await db.any(`SELECT firstName, lastName, email From users where email = "$emailAddress"`, {emailAddress});
}

글쎄, 그것은 간단했다! 기본적으로 대괄호가 없는 $는 일반 문자열로 처리됩니다. 문자열 템플릿 리터럴(백틱)을 유지하거나 대신 따옴표를 사용할 수 있습니다. 그런 다음 모든 작업을 수행하는 db의 any 메소드에 전달되는 객체에 이메일 주소를 덤프하고 있습니다.

이것은 작동합니다:

lookupUserByEmail('[email protected]');

이것은 해커가 예상한 대로 작동하지 않습니다.

lookupUserByEmail('1 or 1=1;');

준비된 진술의 예



이 안전한 방법을 사용하는 다른 언어의 메서드 본문 몇 가지 예:

$stmt = $dbh->prepare("SELECT firstName, lastName, email From users where email = (?)");
$stmt->bindParam(1, $email);
$stmt->execute();



String sqlQuery = "SELECT firstName, lastName, email From users where email = (?)";
PreparedStatement prepStmt = conn.prepareStatement(sqlQuery);
prepStmt.setString(1, "[email protected]");
prepStmt.executeUpdate();
prepStmt.close();

귀하의 ORM은 준비된 진술을 지원합니까?



Active Record는 즉시 사용할 수 있습니다. Sequelize와 유사한 자동입니다. 다음과 같이 끄면 됩니다. idiot says ? 지옥 NO!

추가 읽기



이 주제에 대해 자세히 알아보려면 W3 Schools 주사에 대한 정말 좋은 가이드가 있습니다.

Originally posted on my blog

좋은 웹페이지 즐겨찾기