특징
- DB와 연동된 웹 애플리케이션에서 공격자가 삽입한 SQL 구문이 필터링, 이스케이프 되지 않고 DB를 조작할 수 있는 취약점
- 클라이언트 측에서 입력된 신뢰할 수 없는 데이터가 SQL 쿼리 로직의 일부로 해석되어 DB에서 실행되는 공격
DVWA 실습
- ID를 입력하면 해당 id 에 해당하는 이름을 출력
- SQL Injectiond을 위해 or 뒤에 추가적인 조건을 입력하여 쿼리를 출력
- 1’ or ‘1’=‘1을 입력하면 Id가 1인 것과 참이되는 모든 값을 출력
- Where 절 뒤에 order by 사용 가능한 것을 이용하여 공격
- Column이 두개인 것을 확인
- 여기서 알게된 정보를 통해 union 구문공격에 이용
- Column 정보를 활용하여 추가 DB정보 탈취
- MY SQL에는 information_schema 라는 DB에서 이름 테이블 칼럼 정보를 관리
- Information_schema 의 schemata 테이블로 부터 schema name을 가져오는 쿼리문을 이용하여
DB 이름확인
- DB 이름을 활용하여 테이블 이름 확인
- DB와 테이블을 활용하여 column 명까지 확인
- 계정정보가 담겨 있을 것으로 추정되는 user와 password column 확인 가능
- Column 을 통해 얻은 정보로 아이디와 패스워드에 접근
- MD5 복호화
- SQL Injection 을 통해 모든 아이디와 패스워드 탈취
소스코드 분석
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
switch( $DVWA[ 'SQLI_DB' ] ) {
case 'MySQL':
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row['first_name'];
$last = $row['last_name'];
// Feedback for end user
echo "<pre>ID: {$id}<br/>First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
break;
case 'SQLite':
global $sqlite_db_connection;
//$sqlite_db_connection = new SQLite3($DVWA['SQLITE_DB']);
//$sqlite_db_connection->enableExceptions(true);
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
//$print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo "Caught exception: " . $e->getMessage();
exit(1);
}
if ($results) {
while ($row = $results->fetchArray()) {
// Get values
$first = $row['first_name'];
$last = $row['last_name'];
// Feedback for end user
echo "<pre>ID: {$id}<br/>First name: {$first}<br />Surname: {$last}</pre>";
}
} else {
echo "Error in fetch: ".$sqlite_db->lastErrorMsg();
}
break;
}
}
?>
- 직접적인 사용자 입력 값 사용:
$id 값이 사용자 입력을 통해 그대로 SQL 쿼리에 사용 - SQL 에러 메시지 노출:
die() 함수로 인해 SQL 에러 메시지가 사용자에게 직접 노출 되어 시스템의 구조나 데이터베이스 스키마에 대한 중요한 정보 노출 - Prepared Statements미사용:
SQL 쿼리를 직접 작성하며, 사용자의 입력 값이 바로 쿼리 내에 삽입되어 공격자가 SQL 구문을 삽입가능
대응방안
- Prepared Statements 사용:
SQL 쿼리와 데이터를 분리하여 처리하는 방법인 Prepared Statements를 사용하여 데이터가 SQL 문법으로 해석되지 않도록 처리 - SQL 에러 정보 숨기기:
에러 메시지를 사용자에게 직접 노출하지 말고, 시스템 로그 등에 기록하여 내부적으로만 관리 - 입력값 검증:
입력 값이 숫자일 경우, 숫자인지 확인하는 등의 추가적인 검증을 통해 기본적인 보안 수준 증가
'CERT' 카테고리의 다른 글
웹 모의해킹: SQL Injection(Blind) (2) | 2024.10.05 |
---|---|
웹 모의해킹: Reflected XSS (0) | 2024.10.05 |
웹 모의해킹: Stored XSS (0) | 2024.10.05 |
웹 모의해킹: DOM Based XSS (2) | 2024.10.05 |
웹 모의해킹: Weak Session IDs (2) | 2024.10.05 |