CTF练习001——简单登录




题目地址: http://ctf5.shiyanbar.com/web/jiandan/index.php


解:

(firefox56.0)

step① 

happysneaker.com


step②

试了下,输入  # - = \  以及procedure、union、like等提示 sql inject detected!,输入其他字符总是显示hello,输入 ' or '1  也hello,代码不存在编码解码的问题,关掉页面重新载入会提示SQL注入语法错误,说明还是SQL注入,而且我输入的是  ' or '1 ,错误反馈中多了个  ,0 ,说明后台处理代码会对输入进行截断,找不到思路,那就看看数据包:

happysneaker.com


step③

Firefox设置代理,burp suite捷豹,发现在返回的数据包中存在一个 tips:test.php

happysneaker.com


打开 test.php:


happysneaker.com


右键查看页面源代码:

happysneaker.com

happysneaker.com

happysneaker.com


代码审计:


1' 代码对输入进行匹配过滤,见图中注释,只要检测到其中之一,就提示SQL injection detected!

(关于正则表达式:https://7vs10.com/article/104  )

happysneaker.com


即输入除了上述字符外的其他内容,都会显示 Hello! 但是输入内容会被存储在$info 变量里,提交到 login() 函数进行处理;

happysneaker.com


2' 分析login函数 ,$iv 即 get_random_iv()函数的返回值,因此分析 get_random_iv()函数:

首先chr()函数,对应ASCII码:

happysneaker.com


所以 login()函数的 $iv 变量即接收一个随机16位字符串:

happysneaker.com


再看 $plain 变量,使用serialize()序列化函数,对输入进行了处理,unserialize()当然是反序列化,即还原数据,见下下下图注释;

然后 $cipher 变量:

$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);

使用了 openssl_encrypt() 加密函数,成功返回加密后的字符串,失败返回false,具体原理不求甚解即可:

( 但本题重点在这个参数$method,代码开头是: define("METHOD", "aes-128-cbc");  加密方式为 "aes-128-cbc",而它是有漏洞的

happysneaker.com


举个例子:

happysneaker.com


然后 setcookie() 函数,设置了俩cookie:

happysneaker.com




逻辑大体为:

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后。


作者:蓝天深处
链接:https://www.jianshu.com/p/4c1e5d24d781
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。




step④

逻辑大体上有个了解,然后主要是找到注入点,位于show_homepage()页面中:

$sql="select * from users limit ".$info['id'].",0";

既然是SQL注入,结合正则过滤:

if(preg_match("/\\\|,|-|#|=|~|union|like|procedure/i",$str)){

那么思路就是绕过正则过滤并且让 ".$info['id']."  后面的语句失效即可。试一试: 1;%00   看能不能截断,不行。



关于  %00  截断,0x开头表示16进制,0在十六进制中是00, 0x00就是%00解码成的16进制。重要。

happysneaker.com

happysneaker.com



step⑤

现在的思路就只能在 aes-128-cbc  加密方式上做文章了,因为 aes-128-cbc 存在漏洞,根据经验要用 CBC字节翻转攻击。

burp捷豹发现每次response都包含俩cookie,正好对应了上面的分析:

happysneaker.com


先使用burp,第一次随便输入,点击提交 ,在burp里把request改成 1;%00  ,Foward,显示 Hello;

后退,再次点击提交,burp里删掉 id=。。。 只留下 &submit=Login,Foward,显示 

Hello!rootzz 

第二次无id Post时,并没有直接传入id,但尽然能得到rootzz,为什么?结合代码分析burp数据包:

Hello!rootzz对应

echo '<h1><center>Hello!'.$rows['username'].'</center></h1>';


注入点是:

$sql="select * from users limit ".$info['id'].",0";

在这里代码把解序列化后的数据直接拼接进sql语句中,如果可以控制此处的数据那么就可以造成注入。 

那该如何控制这里的数据呢?可以发现,程序使用了 aes-128-cbc 的加密算法来加密和解密,而这种算法是存在字节反转攻击的。

配合程序在解序列化失败后返回解密后的明文,我们就可以控制密文来得到我们想要的任意明文,从而控制sql语句。


具体操作:

只做到了这里,后续再更。。

Web安全技术分享
请先登录后发表评论
  • 最新评论
  • 总共0条评论