질문 코드는 다음과 같습니다.
Vulnerability Analysis:
질문의 의미에 따르면 여기서 조사하는 내용은 xss 취약점이어야 하며, 취약점 트리거 지점은 에 있어야 합니다. 13-14행. 이 두 줄의 코드 기능은 html <a>
태그를 직접 출력하는 것입니다. 코드의 <a>
标签。代码中的 第3-5行 ,foreach循环 对 $_GET 传入的参数进行了处理,但是这里有个问题。我们看下 第四行 的代码,这行代码针对 $value 进行类型转换,强制变成int类型。但是这部分代码只处理了 $value 变量,没针对 $key 变量进行处理。经过了 第3-5行 的代码处理之后,根据 & 这个符号进行分割,然后拼接到 第13行 的 echo 语句中,在输出的时候又进行了一次 htmlentities 函数处理。 htmlentities 函数主要是会对一些特殊符号进行HTML实体编码。具体定义如下:
htmlentities — 将字符转换为 HTML 转义字符
string htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] )作用:在写PHP代码时,不能在字符串中直接写实体字符,PHP提供了一个将HTML特殊字符转换成实体字符的函数 htmlentities()。
注:htmlentities() 并不能转换所有的特殊字符,是转换除了空格之外的特殊字符,且单引号和双引号需要单独控制(通过第二个参数)。第2个参数取值有3种,分别如下:
ENT_COMPAT(默认值):只转换双引号。
ENT_QUOTES:两种引号都转换。
ENT_NOQUOTES:两种引号都不转换。
这里附上一个 HTML 中有用的字符实体表
经过上面的分析,我们再回到题目,想想如何构造一下攻击 payload 。我们先梳理一些已知信息:
这里的 $query 参数可控
且 htmlentities 函数在这里可逃逸单引号
xss的漏洞触发点在 <a>
标签。
在 <a>
라인 3-5에서 foreach 루프는 $_GET
네 번째 줄을 살펴보겠습니다. 이 코드 줄은
$value변수가 아닌 $value 변수만 처리합니다.
3-5라인의 코드 처리 후 &
기호에 따라 나누어진 뒤13라인의 echo 문에 이어붙이고, 다음과 같은 경우 htmlentities
함수가 다시 수행됩니다. 거래를 출력하고 있습니다.htmlentities 이 함수는 주로 일부 특수 기호에 대한 HTML 엔터티를 인코딩합니다. 구체적인 정의는 다음과 같습니다.
htmlentities - 문자를 HTML 이스케이프 문자로 변환
/?a'onclick%3dalert(1)%2f%2f=c기능: PHP 코드를 작성할 때 엔터티 문자를 문자열에 직접 쓸 수 없습니다. PHP는 HTML 특수 문자를 문자열로 변환하는 방법을 제공합니다. 엔터티 문자에 대한 htmlentities() 함수.
참고: htmlentities()
는 모든 특수 문자를 변환하지는 않습니다. 공백을 제외한 특수 문자를 변환하며, 작은따옴표와 큰따옴표는 (두 번째 매개변수를 통해) 별도로 제어해야 합니다. 두 번째 매개변수에는 다음과 같이 세 가지 값이 있습니다.htmlentities 함수는 다음과 같습니다. 여기에서 탈출 가능한 작은따옴표
<a>
태그에 있습니다. 🎜<a>
에서는 다음과 같은 🎜javascript🎜 이벤트를 통해 js 코드를 실행할 수 있습니다. 🎜onclick🎜 이러한 유형의 이벤트이므로 최종 poc 구성은 🎜<?php require 'db.inc.php'; if(isset($_REQUEST['username'])){ if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['username'])){ die("Attack detected!!!"); } } if(isset($_REQUEST['password'])){ if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['password'])){ die("Attack detected!!!"); } } function clean($str){ if(get_magic_quotes_gpc()){ $str=stripslashes($str); } return htmlentities($str, ENT_QUOTES); } $username = @clean((string)$_GET['username']); $password = @clean((string)$_GET['password']); $query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';'; #echo $query; $result=mysql_query($query); while($row = mysql_fetch_array($result)) { echo "<tr>"; echo "<td>" . $row['name'] . "</td>"; echo "</tr>"; } ?>🎜🎜🎜🎜사례 분석🎜🎜이 사례 분석에서는 DM 기업 웹사이트 구축 시스템 v201710의 🎜sql 주입 취약점🎜을 선택하여 분석합니다. 우선, 다음과 같이 cnvd에서 몇 가지 관련 정보를 볼 수 있습니다. 🎜🎜🎜🎜🎜취약점 알림에서 몇 가지 유용한 정보를 찾을 수 있습니다. 취약점은 빌드할 때 백그라운드 로그인 포트에 있습니다. 🎜admindm-yourname /g.php🎜 파일에 있습니다. 이 파일을 열고 🎜admindm-yournamemod_common/login.php🎜 파일로 리디렉션되는 것을 확인하세요. 따라서 취약점 트리거 지점은 이 파일에 있어야 합니다. 🎜🎜🎜🎜🎜Open 🎜admindm-yournamemod_common/login.php🎜 이 파일을 이용하면 취약점의 위치를 한눈에 알 수 있으며, 다음과 같이 관련 코드의 일부를 가로챌 수 있습니다. 🎜🎜🎜🎜🎜🎜15행🎜 입니다. 스플라이싱 방식을 통해 select 문에 직접 삽입되는 SQL 인젝션 취약점이 있음은 자명하다. 🎜15행🎜의 🎜$user🎜 변수는 🎜POST🎜를 통해 제출되며 해당 값은 제어 가능합니다. 그러나 위 그림의 🎜Line 3🎜 코드는 🎜htmlentitiesdm🎜 함수를 호출하여 🎜POST🎜 데이터를 처리합니다. 우리는 이 🎜htmlentitiesdm🎜 함수를 사용합니다. 이 기능은 🎜comComponent/dm-config/global.common.php🎜 파일에 있습니다. 키 코드는 다음과 같이 차단됩니다. 🎜🎜🎜🎜
这个函数是调用 htmlentities 函数针对输入的数据进行处理。前面我们已经介绍过了这个函数的用法,这里这个函数的可选参数是 ENT_NOQUOTES ,也就是说两种引号都不转换。下面我们来看个小例子:
这里我猜测开发者应该是考虑到了xss的问题,但是由于 htmlentities 这个函数选择的参数出现了偏差,导致这里我们可以引入单引号造成注入的问题。
我们看看最新版是怎么修复,使用 beyond compare 对比两个版本代码的差别。
新版修复的时候将可选参数修改为 ENT_QUOTES ,这个参数的作用就是过滤单引号加双引号,我们来看看下面这个例子,就很容易明白了这个参数的作用了。
这里因为没有回显,所以是盲注,下面是验证截图:
针对 htmlentities 这个函数,我们建议大家在使用的时候,尽量加上可选参数,并且选择 ENT_QUOTES 参数。
我们看看对比的效果
看完了上述分析,不知道大家是否对 htmlentities 函数在使用过程中可能产生的问题,有了更加深入的理解,文中用到的代码可以从 这里 下载,当然文中若有不当之处,还望各位斧正。如果你对我们的项目感兴趣,欢迎发送邮件到 hongrisec@gmail.com 联系我们。Day12 的分析文章就到这里,我们最后留了一道CTF题目给大家练手,题目如下:
<?php require 'db.inc.php'; if(isset($_REQUEST['username'])){ if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['username'])){ die("Attack detected!!!"); } } if(isset($_REQUEST['password'])){ if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['password'])){ die("Attack detected!!!"); } } function clean($str){ if(get_magic_quotes_gpc()){ $str=stripslashes($str); } return htmlentities($str, ENT_QUOTES); } $username = @clean((string)$_GET['username']); $password = @clean((string)$_GET['password']); $query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';'; #echo $query; $result=mysql_query($query); while($row = mysql_fetch_array($result)) { echo "<tr>"; echo "<td>" . $row['name'] . "</td>"; echo "</tr>"; } ?>
# Host: localhost (Version: 5.5.53) # Date: 2018-08-05 12:55:29 # Generator: MySQL-Front 5.3 (Build 4.234) /*!40101 SET NAMES utf8 */; # # Structure for table "users" # DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `pass` varchar(255) DEFAULT NULL, `flag` varchar(255) DEFAULT NULL, PRIMARY KEY (`Id`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; # # Data for table "users" # /*!40000 ALTER TABLE `users` DISABLE KEYS */; INSERT INTO `users` VALUES (1,'admin','qwer!@#zxca','hrctf{sql_Inject1on_Is_1nterEst1ng}'); /*!40000 ALTER TABLE `users` ENABLE KEYS */;
위 내용은 HTML 엔터티 기능의 오용으로 인한 취약점을 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!