BUUCTF
本文最后更新于:10 个月前
EasySql
先用用户名:1 密码:1’ 测试注入,页面报错,可能存在注入点,并且是字符型。
密码传入***1’ order by 4 #***时报错,判断出数据库有三个字段。
准备爆数据库名,二分法传入***1’ or (ascii(substr(database(),0,1))<128)#***,结果直接拿到了flag。
题后反思:因为传入***1’ or (ascii(substr(database(),0,1))<128)#*导致后端查询语句变成select * from 数据库名 where username = ‘1’ and pasword =’1’ or (ascii(substr(database(),0,1))<128)#’***因为and优先级高于or,于是整个句子变成了两个部分:
select * from 数据库名 where username = ‘1’ and pasword =’1’ 和
or (ascii(substr(database(),0,1))<128)#’
虽然用户名密码判断是错的,但是数据库名的第一个字符的ascii码确实小于128,为真,二者用or相连,返回为true,故登陆成功获取到flag;
但是这样做实际上是走弯路了,这道题布尔盲注不是最优解,实际上直接构造密码为***1’ or 1=1#***在原理上是和上面误打误撞拿到flag是一样的,但是少走了很多弯路。
easy_sql
先传入1,返回一个字符串,传入1’,报错
可能存在sql注入,并且是字符型的。传入***’ order by 4#***,报错。
传入***’ order by 3#,报错。传入‘ order by 2#***不报错,判断表里有2个字段。
联合查询尝试失败,select被ban。尝试构造无字母数字的语句。编写脚本
1 |
|
得到select,尝试能否绕过
1 |
|
还是没绕过,暂时放弃这条路。
查找学习show databases爆数据库名。
show tables爆表名,好臭的表名啊(。
‘; show columns from `1919810931114514`;#爆字段名(表名要用反引号引起来)
万事俱备,只欠select,直接select不行,去查找能代替select的,果不其然,找到了handler语句。
1 |
|
1 |
|
最终构造payload:
1 |
|
拿到flag。
反思:除了上面的方法寻找mysql中的其他查询语句外,看了大佬们的wp后学到了更多的思路和相关知识,这道题还可以通过预编译得到flag。
预编译相关语法:
1 |
|
以及一个mysql语句concat(str1,str2),将str1与str2连接起来返回连接后的字符串;或者mysql的hex()函数把语句变成十六进制同样可以绕过select的过滤。
步骤如下:
1 |
|
1 |
|
1 |
|
构造
1 |
|
然后提示set被ban了,但是用的是strstr(),区分大小写,所以大写绕过
1 |
|
十六进制绕过的步骤如下:
打开mysql命令行输入
1 |
|
得到一串十六进制字符串。
构造预处理语句:
1 |
|
set同样大写绕过,payload:
1 |
|
GET到flag;
另外一种思路,从最开始看到题目的时候就在想直接输入1回显的数组是来自哪里的呢,但是最开始做的时候爆了191981093114514表就没爆words表的字段名了,因为191981093114514表里只有一个元素,所以推测回显内容是words表里的,爆words字段名
1 |
|
推测回显内容来自于data字段;
思路就是把words表改名为其他的名字,191981093114514改名为words,把其中的flag字段改名为id(或者在xinwords表里增加一列id),最后传入***1’ or 1=1#***使查询结果为true爆出words所有字段内容。
相关语句如下:
1 |
|
payload1:
1 |
|
payload2:
1 |
|
PingPingPing
做这道题时想到前面做过的另外一题(新生赛exec)。总结了以下联合执行的符号作用:
1 |
|
传入
1 |
|
说实话一开始没反应过来space是空格的意思就没想着空格被过滤了(,单纯以为是表达错误不需要空格然后把空格删掉发现可以执行,直到下面cat命令没法正常执行时才反应过来是空格被ban了(。
提示空格被ban了,传入
1 |
|
或者
1 |
|
回显提示目录里有flag.php和index.php
直接
1 |
|
然后提示空格被ban了。参考了大佬们的博客,大佬总结了以下几点绕过空格的方法:
1 |
|
逐一试下来发现$IFS$1是可行的但是提示flag被ban了(悲)
既然看不了flag又不知道过滤规则,反正还有个index.php能看
1 |
|
密密麻麻的这么多都被过滤了,括号引号星号全员过滤。。。想起之前从学长那里学来的星号绕过,也不能用了,没有头绪的时候。
正巧刚刚在学习绕过空格过滤的时候看到一篇博客,https://www.cnblogs.com/GLory-LTF/p/15359485.html。里面有讲到如果cat字符被ban了但是非得用cat命令,这里介绍了一种命令拼接绕过(记小本本)。
理论知道了,开始实践
嗯。。属于是学了点知识不会灵活变通了,再次求助大佬,给出的payload是
1 |
|
又有收获了,拼接绕过不一定要每个字母都拼接,看着这个payload有个想法,如果把$a的位置在flag四个位置改变会怎么样。实践。
替换字符f的位置
替换字符l的位置
替换字符a的位置
看来只有g的位置可以。然后注意到$a是代码中原有的变量,如果构造payload时用的是b变量会怎么样呢
也是可行的
[HCTF 2018]admin 1
记一次flask的session伪造:
先是发现admin用户被注册了,注册登陆界面经测试均不存在sql注入,先随便注册一个用户看看:
挨个页面去检索信息,最后在修改密码的页面的源码中发现了网站项目的代码:
现在做发现已经仓库404了(悲)
总而言之就是在flask在设置session时只是进行了简单的签名,然后放在前端的cookie中,
Flask中的Session,它是存在于客户端的,也就是说我们在进行登录过后可以看到自己的Session值,而当我们对这个Session值进行base64解码后,就可以读取它的具体内容。 对应Flask,它在生成session时会使用app.config[‘SECRET_KEY’]中的值作为salt对session进行一个简单处理,那么这里的话,只要key不泄露,我们就只能得到具体内容,但是无法修改具体内容,因此这个时候就引发了一个问题,当key泄露的时候,就出现了内容伪造的情况,比如具体内容为{‘name’:’123’},而当我们掌握key时,可修改内容为{‘name’:’admin’}
这道题其实就是在源码中没有把敏感数据去除导致secret_key泄露,去网上找大家的secret_key:”ckj123”
从cookie获取session:
用flask session工具解个码:
用法参考:https://github.com/noraj/flask-session-cookie-manager
改成admin重新生成一下session:
修改cookie:
另外此题也有其他具有参考意义的两种解法,unicode欺诈还有条件竞争: