본문 바로가기
Database/MySQL & RDBMS

AWS EC2 서버 호스팅한 사이트 DB 털린 이야기 (SQL 인젝션 방어하기)

by img 2021. 11. 27.

취업을 위해 포트폴리오 용으로 만들었었던 사이트에서 자랑은 아니지만 DB 공격을 1년동안 총 3번이나 당했다...

SQL 인젝션은 쉽게말하면, 웹사이트에서 <input> 박스가 있을 때 그 곳에 입력한 값들은 보통 DB로 이동하기 때문에, 그 안에 쿼리문을 작성해서 전송을 하게 되면 그 쿼리문에 따라 해당 DB의 데이터를 가져올수도, 데이터베이스 전체를 삭제해버릴 수도 있다. 공격의 난이도에 비해 피해정도는 매우 커서 웹사이트를 만들 때 매우 유의해야한다고 한다. (실제 공격방법을 찾아보니 너무 간단했다.)

첫번째로 공격을 당했을 때는 그저 AWS EC2에서 호스팅할때 보안그룹 인바운드 아웃바인드를 잘못 설정해줘서 그냥 해킹을 당했나보다 하고 보안그룹설정과 어려운 비밀번호로 바꿔줬는데, 몇주 뒤에 보니 또 내 DB가 날라가있었다. 취업을 위해 만들었던 포트폴리오였는데, 어쨌든 그 땐 취업은 우선 한 상태니 그냥 날아간 더미데이터들은 날아간채로 놔두고, 그냥 테이블만 다시 생성한 상태로 몇개월을 잊고 살았었다. 그러다가 몇달 뒤 다시 들어가봤는데 또 내 DB 테이블들이 날아가있었다ㅠㅠㅠㅠㅠㅠ

그래도 나름 프로그래밍 처음 공부할 때 열심히 만들었던 사이트이고, AWS EC2로 소정의 비용까지 내가면서 서버에 올려논 사이트인데, 이렇게 계속 개복치처럼 정기적으로 날아가버리는게 억울해서(?) 이참에 테이블을 다시 생성하면서 SQL Injection 방어도 같이 하려고 한다. 

우선 공격을 당한 내 사이트는 Spring framework + MySQL을 이용했고, 사이트를 들어가면 이런 오류가 뜬다. 

 Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException:

DB 쿼리가 잘못되었을 때 뜨던 오류이다. 테이블에서 SELECT해서 데이터를 불러와야하는데 해당 테이블이 통째로 날아가버렸으니 테이블을 찾을 수가 없기 때문에 저렇게 뜨는 것이다. 

그래서 내 AWS EC2 서버에 들어가 직접 데이터베이스를 확인을 해봤다. 

SHOW TABLES; 를 해서 테이블 상태를 보니 내 테이블은 다 날아가있었고, WARNING이라는 테이블 하나만 덩그러니 있었다.그래서 SELECT * FROM WARNING; 을 해보니 

To recover your lost databases and avoid leaking it: visit http://o42xfh5kao7mrtesnok5jgdsfagjsgzxlxdlpkpd2x6lpckhzk225yad.onion and enter your unique token 31519b1f7c1b2a9a and pay the required amount of Bitcoin to get it back. Databases that we have: test_mysql. Your databases are downloaded and backed up on our servers. If we dont receive your payment in the next 9 Days, we will sell your database to the highest bidder or use them otherwise. To access this site you have use the tor browser https://www.torproject.org/projects/torbrowser.html

뭐 이런식으로 데이터를 남겨놓았었다. 데이터 살리고 싶으면 비트코인 내놔라라는 얘기....

( 참고로 맨처음 당했을 때 남겨놨던 멘트는 다음과 같다 (적어놨었음) : To recover your lost Database and avoid leaking it: Send us 0.015 Bitcoin (BTC) to our Bitcoin address 1HpjptzGzoYSXCCmzgn7r4zsYo3TgJ5ma9 and contact us by Email with your Server IP or Domain name and a Proof of Payment. Your Database is downloaded and backed up on our servers. Backups that we have right now: test_mysql. Any email without your server IP Address or Domain Name and a Proof of Payment together will be ignored. If we dont receive your payment in the next 10 Days, we will make your database public or use them otherwise.)

마찬가지로 비트코인 내놔라....


SQL 인젝션을 방어하는 방법은 여러가지가 있다.

클라이언트단에서 input값이 들어왔을 때 javascript로 정규표현식을 활용한 메소드를 통해 필터링을 해줘도 되고, 서버단에서 필터링를 해줘도 된다. 아니면 라이브러리를 활용할 수도 있다. 

function SQLFiltering(str){
  str = str.replace("/\s{1,}1\=(.*)+/","",str); // 공백이후 1=1이 있을 경우 제거
  str = str.replace("/\s{1,}(or|and|null|where|limit)/i"," ",$str); // 공백이후 or, and 등이 있을 경우 제거
  str = str.replace("/[\s\t\'\;\=]+/","", str); // 공백이나 탭 제거, 특수문자 제거
  return str;
}

이런식으로 필터링을 해주면 그래도 1차적인 방어는 가능하다

댓글