【DVWA】SQL Injection

SQL injection is one of the common vulnerabilities of websites. It can directly get all the contents of the database on the website, and it is listed as the "two evils" of website attacks together with XXS. After setting up DVWA ( https://my.oschina.net/u/3776619/blog/1803401 ) and setting the security level of DVWA to low, a sql attack can be simulated well. Through personal experience, we should be able to leave this vulnerability open to attack when developing a website in the future.

 

1. SQL injection display in DVWA

Open the SQL Injection module, at first glance, this is a very common input box. For example, if we enter 1, he can give feedback very well, as shown in the following figure:

But if you enter 1', you will find that this website reports an error and cannot provide feedback very well, which means that this website has a SQL vulnerability:

The reason for this can be seen at a glance in the source code of this webpage. The source code of this webpage is in .\DVWA\vulnerabilities\sqli\source\low.php, as follows:

<?php

if( isset( $_REQUEST[ 'Submit' ] ) ) {
	// Get input
	$id = $_REQUEST[ 'id' ];

	// Check database
	$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
	$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

	// Get results
	while( $row = mysqli_fetch_assoc( $result ) ) {
		// Get values
		$first = $row["first_name"];
		$last  = $row["last_name"];

		// Feedback for end user
		$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
	}

	mysqli_close($GLOBALS["___mysqli_ston"]);
}

?>

Note that there is no protection for the $query statement, which means that $id=1, that is, $query evolves into SELECT first_name, last_name FROM users WHERE user_id = '1' Fortunately, SELECT first_name, last_name FROM users WHERE user_id = ''' is definitely wrong, what if SELECT first_name, last_name FROM users WHERE user_id = '1' or '1=1'? Is this query must be true, and the where statement does not take effect, the first_name and last_name of the entire users table are found out? That is, we enter in the input box, 1' or '1=1.

The result is as follows, as expected:

 

Second, the prevention of SQL injection

In fact, the prevention of SQL injection is not difficult. We only need to verify the passed parameters. If it is not legal, simply reject the request and it will be done. There are the following situations:

(1) If your input box requires a number type, determine whether it is a number, if not, directly reject the request

(2) If it is a formatted type (such as date, email, phone number, ID number, etc.), it is judged that it does not conform to the format. If it does not conform to the format, the request is rejected.

(3) If it is a string type, there is no special format, and the length of the string needs to be checked. If the length is greater than the defined length of the field in the database, the request will be rejected directly. For example, for the above id, if the database is defined as varchar(1), if the input exceeds 1 character, the request will be rejected directly.

In .\DVWA\vulnerabilities\sqli\source\impossible.php, DVWA directly provides SQL injection prevention solutions, as follows:

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
	// Check Anti-CSRF token
	checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

	// Get input
	$id = $_GET[ 'id' ];

	// Was a number entered?
	if(is_numeric( $id )) {
		// Check the database
		$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
		$data->bindParam( ':id', $id, PDO::PARAM_INT );
		$data->execute();
		$row = $data->fetch();

		// Make sure only 1 result is returned
		if( $data->rowCount() == 1 ) {
			// Get values
			$first = $row[ 'first_name' ];
			$last  = $row[ 'last_name' ];

			// Feedback for end user
			$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
		}
	}
}

// Generate Anti-CSRF token
generateSessionToken();

?>

It can be seen that a strict review has been made on the type and length of an input id, as well as the number of returned results, which is foolproof.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325208035&siteId=291194637