본문 바로가기

old/Cyber Security

Assignment: 로그인 로직&우회 연구

반응형

1. 쿼리 인풋 길이 제한

우회법

여전히 짧은 명령어는 통함 ex) ' OR '1' = '1

2. 주석 제한 (# /* */) 정규식 제거

$str = preg_replace('/#|\\/\\*|\\*\\//', '', $str);

우회법

//** **//으로 할 결우, 가운데 주석만 제거됨.

3. 특수 문자 제한(* ” ‘ - ( ) < > /* */ = ; or and) 정규식으로 제거

$str = preg_replace('/\\*|\\"\\s|\\\\\\'|-\\s|\\)\\s|<\\s|\\>\\s|\\/\\*.*?\\*\\/|=|;\\s|\\sor\\s|and\\s/', '', $str);

우회법

//** **//으로 할 결우, 가운데 주석만 제거됨.

4. [빈칸]SQL명령어[빈칸] 제한, select, show, create, insert, update, delete, drop, alter

$sql = preg_replace('/(SELECT|UPDATE|DELETE|INSERT|FROM|WHERE|AND|OR|ORDER BY|GROUP BY|HAVING)\\s.*?;/si', '', $sql);

우회법

제거시, SESELECTLECT 라고 하면 결과적으로 SELECT가 되서 가능함

제한시, 아스키코드를 넣으면 된다. ‘SELECT%20%2A%20FROM%20users%20WHERE%20id%20%3D%201’

5. 미리 앞쪽과 뒤쪽 데이터를 저장해두고 비교 검수

Select * from user_table where username=’$_username’ and password=’$_password’; 일때,

front=’Select * from user_table where username=\’’;

back=’\’’;

이라고 넣어서 substr(0,41), substr(-2)으로 비교.

우회법

공격자가 이런식으로 인증을 한다는것을 안다는 가정하에 주석을 사용하지 않고 검색하면 가능.

6. 인풋에 스페이스 있으면 쿼리로 간주

우회법

단순하게 한줄 주석은 스페이스가 없음.

아스키 코드를 사용해도 됨.

7. 추가 인증(이메일, 핸드폰)

우회법

공격자가 이메일과 핸드폰을 이미 해킹했다면. 이것도 해킹가능

8. response 검증

미리 각 명령어에 대해 반드시 나오는 더미데이터를 미리 넣어두고 이 더미 데이터가 나오지 않는다면 SQL Injection으로 간주

우회법

맨 위에 더미데이터가 있다는것을 안다면 그를 회피해서 사용가능

9. 횟수 제한: 로그인 실패 5번이상

우회법

공격자가 짧은 시간내에 알아낸다면 막기 불가

10. Stored Procedure를 사용 -지정된 형식의 데이터가 아니면 Query 가 실행되지 않음

php용 Stored Procedure는 잘 모르므로.. 일단 MySQL+JAVA+javalin 코드로 대체. 나중에 php코드로 대체 할것.

 
String sql = “SELECT * FROM user_table where username=? and password=?”;
PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, account.getUsername());
preparedStatement.setString(2, account.getPassword());

우회법

여전히 select 커맨드는 작동하므로, UNION SELECT credit_card_number, NULL, NULL FROM credit_cards WHERE user_id = 1 같은 공격을 하면 가능함.

11. 아이디와 비밀번호 암호화해서 검증

서버에 할당해놓은 개인키를 사용해서 아이디와 비번을 해쉬코드로 변환한다음 비교, 검증. SQL 인젝션은 기본적으로 쿼리문이 들어가므로, 막을수 있음.

서버에는 아이디와 비번을 sha256한 값만 저장되어 있고. 해싱을 할떄 서버의 개인키도 붙여서 해싱을 해야 서버에 저장된 값이 나옴.

즉 아이디가 1111, 비번이 2222, 서버 개인키가 test라고 친다면,

아이디는 1111test를 해시한 값인 5F9D06E3130888B3D405124CA5409F7EA5DD7DE48F098B3E7CEC09ED7E1775EF가 되고

비밀번호는 2222test를 해시한 값인 9227BD059199C44E900F2D0734F278B1D1BE1FCB252E54E73D9F9D6E37DCC264가 된다.

즉 쿼리문은

select * from users where id = ‘5F9D06E3130888B3D405124CA5409F7EA5DD7DE48F098B3E7CEC09ED7E1775EF’;

가 된다.

해싱한 값이 select * from users where.. 이런식으로 나올수 없으므로 안전함.

db가 엄청 커진다.

속도도 엄청 느려진다.

해시 콜리젼이 일어나면 다른 값도 같다고 인식해서 몇몇 아이디는 없지만 쓸수 없는 상태가 된다.

우회법

sql 인젝션으로는 불가능할거 같다.

운으로 해시 콜리전이 일어나서 같은 해시값이 나온다면 가능할듯. 부르들포스로.

반응형