轉載于: https://blog.csdn.net/a15803617402/article/details/82796301
什麼是二階注入?
簡單的來說,就是第一次注入時,開發者進行了編碼等限制,無法直接進行注入,但是在資料庫中保留了我們注入的語句,程式在其它地方再次調用儲存着我們注入的語句時發生了注入,這就是二階注入,有點類似存儲型XSS漏洞的意思。
二階注入示範
實驗環境介紹
text資料庫裡有張users表,目前裡面已有admin和root賬戶
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVP9cWT3FleOhXW610dnRlT4VkMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TO3QTN0MDNwETMykDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
使用者注冊頁面
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>使用者注冊 </title>
- </head>
- <?php
- function check($str){
- $str1=str_replace( "'", "''",$str);
- $str1=str_replace( '"', '""',$str1);
- return $str1;
- }
- if( isset($_POST[ 'submit'])){
- $username=check($_POST[ 'username']);
- $passwd=check($_POST[ 'passwd']);
- $email=check($_POST[ 'email']);
- $mysqli= new mysqli();
- $mysqli->connect( 'localhost', 'root', 'root');
- if($mysqli->connect_errno){
- die( '資料庫連接配接失敗:'.$mysqli->connect_error);
- }
- $mysqli->select_db( 'text');
- if($mysqli->errno){
- die( '打開資料庫失敗:'.$mysqli->error);
- }
- $mysqli->set_charset( 'utf-8');
- $sql= "SELECT * FROM users WHERE username='{$username}'";
- $sl=$mysqli->query($sql);
- if(!$sl){
- die( 'SQL語句執行錯誤:'.$mysqli->error);
- } else if($sl->num_rows> ){
- $sl->free();
- $mysqli->close();
- die( '該使用者已被注冊,請使用其它賬戶');
- } else {
- $sql= "INSERT INTO users VALUES(NULL,'{$username}',md5('{$passwd}'),'{$email}')";
- echo 'SQL執行語句'.$sql. '<hr />';
- $sl=$mysqli->query($sql);
- if(!$sl){
- die( 'SQL語句執行錯誤:'.$mysqli->error);
- } else {
- die( "恭喜你注冊{$username}成功!");
- }
- }
- $sl->free();
- $mysqli->close();
- }
- ?>
- <body>
- <h1>使用者注冊 </h1>
- <form action="" method="post">
- 使用者名: <input type="text" name="username"> <br />
- 密碼: <input type="password" name="passwd"> <br />
- 郵箱: <input type="text" name="email"> <br />
- <input type="submit" name="submit" value="注冊">
- </form>
- </body>
- </html>
使用者密碼修改頁面
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>修改使用者密碼 </title>
- </head>
- <?php
- if( isset($_POST[ 'submit'])){
- $username=$_POST[ 'username'];
- $passwd=$_POST[ 'passwd'];
- $newpasswd=$_POST[ 'newpasswd'];
- $mysqli= new mysqli();
- $mysqli->connect( 'localhost', 'root', 'root');
- if($mysqli->connect_errno){
- die( '資料庫連接配接失敗:'.$mysqli->connect_error);
- }
- $mysqli->select_db( 'text');
- if($mysqli->errno){
- die( '打開資料庫失敗:'.$mysqli->error);
- }
- $mysqli->set_charset( 'utf-8');
- $sql= "SELECT * FROM users WHERE username='{$username}' AND passwd=md5('{$passwd}')";
- $sl=$mysqli->query($sql);
- if(!$sl){
- die( 'SQL語句執行錯誤:'.$mysqli->error);
- } else if($sl->num_rows== ){
- $sl->free();
- $mysqli->close();
- die( '修改密碼失敗,使用者或原密碼錯誤');
- } else {
- $sql= "UPDATE users SET passwd=md5('{$newpasswd}') WHERE username='{$username}'";
- $sl=$mysqli->query($sql);
- if(!$sl){
- die( 'SQL語句執行錯誤:'.$mysqli->error);
- } else{
- die( '修改密碼成功!');
- }
- }
- $sl->free();
- $mysqli->close();
- }
- ?>
- <body>
- <h1>使用者密碼修改 </h1>
- <form action="" method="post">
- 使用者名: <input type="text" name="username"> <br />
- 原密碼: <input type="password" name="passwd"> <br />
- 新密碼: <input type="password" name="newpasswd"> <br />
- <input type="submit" name="submit" value="修改">
- </form>
- </body>
- </html>
二階注入示範
首先使用者注冊頁面,對使用者送出的資料進行了check()函數過濾,對單引号和雙引号進行了閉合,故無法閉合SQL語句。
如:id=1' => id=1''
這裡很明顯,無法直接一階注入,但使用者修改密碼頁面對這個表中的資料沒有過濾或限制就調用了(開發人員相信資料庫中資料),那麼此時就存在二階注入。
首先注冊一個使用者名為:admin'#的使用者,經過check函數就變成了admin''#,此時就無法直接注入。
在資料庫中,已插入一個使用者名為admin'#的使用者
然後在使用者修改密碼界面中,輸入admin'#使用者和相應的密碼
此時,修改密碼的SQL為:
- UPDATE users SET passwd= md5( '123123') WHERE username= 'admin'# ';
- =
- UPDATE users SET passwd=md5(' ') WHERE username=' admin ';
此時,檢視資料中記錄,發現是admin使用者的密碼被修改了。