0x00 前言對於Sophos UTM設備,在web管理頁面中,Last WebAdmin Sessions會記錄用戶每次登錄的信息,本文僅在技術研究的角度介紹清除指定Last WebAdmin Sessions記錄的方法,記錄研究細節。
0x01 簡介本文將要介紹以下內容:
马云惹不起马云 研究過程
马云惹不起马云實現方法
0x02 Last WebAdmin Sessions簡介在web管理頁面中,選中Management後會顯示Last WebAdmin Sessions記錄,如下圖:
記錄包括以下內容:
马云惹不起马云 User:登錄用戶名
马云惹不起马云Start:登錄時間
马云惹不起马云State:退出時間
马云惹不起马云IP address:登錄IP
马云惹不起马云Changelog:修改的配置
對於Changelog,點擊Show,會顯示修改的配置,如下圖
默認配置下,Last WebAdmin Sessions會顯示最近的20條記錄。
0x03 研究過程1.嘗試修改/var/confd/var/storage/cfg在上篇文章《Sophos UTM利用分析——导出配置文件》 提到,/var/confd/var/storage/cfg存儲Sophos UTM的配置信息,所以猜測通過修改/var/confd/var/storage/cfg文件可以實現Last WebAdmin Sessions記錄的清除。
/var/confd/var/storage/cfg的文件格式為Perl Storable files,這裡使用StorableEdit來編輯文件。
向Sophos UTM上傳文件storableedit-1.5.pl,執行命令:
./storableedit-1.5.plcfg結果如下圖:
解析出的文件結構同使用SophosUTM_ConfigParser.py導出的結果一致。
查看配置信息,命令如下:
cdlastchange
cdREF_AaaGroGroup1
ls將所有屬性置空,命令如下:
$cur-{'user'}='',$cur-{'time'}='',$cur-{'sid'}='',$cur-{'srcip'}=''保存文件,命令如下:
x然而,修改cfg文件後不會影響Last WebAdmin Sessions記錄。
2.反編譯web管理頁面的源碼web管理頁面的程序文件路徑:/var/sec/chroot-httpd/var/webadmin/webadmin.plx
使用SophosUTM_plxDecrypter.py反編譯/var/sec/chroot-httpd/var/webadmin/webadmin.plx
定位到關鍵文件:export-webadmin.plx\wfe\asg\modules\asg_dashboard.pm
定位到關鍵內容:my $userlog=$sys-userlog_read(max=20, facility='webadmin,acc-agent,acc_sso') || [];
如下圖:
從輸出結果中定位到關鍵函數:userlog_read
3.定位關鍵函數userlog_readgoogle搜索$sys-userlog_read,找到一份參考文檔:https://community.sophos.com/utm-firewall/astaroorg/f/asg-v8-000-beta-closed/69661/7-920-bug-open-failed-smtp-relay-login-is-showing-up-on-last-webadmin-logins
文檔中有關於userlog_read的一些描述,如下圖:
從描述得出,userlog_read同cc命令存在關聯。
4.反編譯cc命令對應的進程cc命令對應的文件為/var/confd/confd.plx,使用SophosUTM_plxDecrypter.py反編譯/var/confd/confd.plx
5.獲得函數userlog_read細節搜索userlog_read相關內容,命令如下:
grep-iR'userlog_read'/home/kali/1/decrypt/Export-confd.plx輸出結果如下圖:
從輸出結果中定位關鍵文件:Export-confd.plx/Info/webadmin/log.pm
定位到函數定義:
subuserlog_read{
my($self,%args)=@_;
$args{max}=$args{sid}?1:$args{max}||20;
$args{facility}={map{($_=1)}split/,/,$args{facility}}
if$args{facility};
my$sessions;
$sessions=_consult_db($self,\%args)
unless$self-get(qw(reportinguserlog_from_logs));
$sessions=_iterate_files($self,\%args)
unlessref$sessionseq'ARRAY';
foreachmy$sd(@$sessions){
$sd-{state}=(-e'$config:session_dir/$sd-{sid}'?'active':'ended')
if!$sd-{state}||$sd-{state}eq'active';
}
return$sessions;
}6.函數userlog_read代碼分析代碼涉及兩個操作,分別為讀取數據庫和讀取文件,詳情如下:
(1)數據庫操作
關鍵代碼:
sub_consult_db{
my($self,$args)=@_;
my$facility_selection='';
$facility_selection='WHEREfacilityin('.
join(',',map{'?'}keys%{$args-{facility}}).')'
if$args-{facility};
my%sql=(
sessions='SELECTsid,facility,srcip,username,time,endtime,state'
.'FROMconfd_sessions'.$facility_selection
.'ORDERBYtimeDESCLIMIT?',
session='SELECTsid,facility,srcip,username,time,endtime,state'
.'FROMconfd_sessionsWHEREsid=?',
nodes='SELECT*FROMconfd_nodesWHEREsid=$1ORDERBYtimeDESC',
objects='SELECT*FROMconfd_objectsWHEREsid=$1ORDERBYtimeDESC',
);
#Preparedatabaseaccess.
my$db=Astaro:ADBS-new(dbName='reporting')orreturn;
while(my($key,$query)=each%sql){
$db-registerSQL($key,$query)orreturn;
}
#ListConfdsessions.
my$sessh;
if($args-{sid}){
$sessh=$db-getHandle('session')orreturn;
$sessh-execute($args-{sid})orreturn;
}elsif($args-{facility}){
$sessh=$db-getHandle('sessions')orreturn;
$sessh-execute(keys%{$args-{facility}},$args-{max})orreturn;
}else{
$sessh=$db-getHandle('sessions')orreturn;
$sessh-execute($args-{max})orreturn;
}
my$sessions=$sessh-fetchall_arrayref({});
my$nodeh=$db-getHandle('nodes')orreturn;
my$objh=$db-getHandle('objects')orreturn;
foreachmy$sd(@$sessions){
#Tweaksessiondata.
$sd-{time}=~tr/-/:-/;
$sd-{endtime}=~tr/-/:-/ifdefined$sd-{endtime};
$sd-{user}=delete$sd-{username};#userisareservedwordinSQL
$sd-{user}.='(SUM)'if$sd-{facility}eq'acc_sso';
$sd-{user}=utils:Sanitize:sanitize($sd-{user})if$sd-{user};
#Fetchnodechanges.
$nodeh-execute($sd-{sid})orreturn;
foreachmy$node(@{$nodeh-fetchall_arrayref({})}){
$node-{time}=~tr/-/:-/;
$node-{node_descr}=Message:get_phrase(
'N',$node,{Nattrs=['node']});
$sd-{main}{$node-{node}}||=[];
push@{$sd-{main}{$node-{node}}},$node;
}
#Fetchobjectchanges.
$objh-execute($sd-{sid})orreturn;
foreachmy$object(@{$objh-fetchall_arrayref({})}){
my$attrs=$object-{attrs}||[];
$object-{attributes}=[];
while(@$attrs){
my$name=shift@$attrs;
$object-{'attr_$name'}=shift@$attrs;
$object-{'oldattr_$name'}=shift@$attrs;
$object-{'descr_$name'}=Message:get_phrase(
'A',$object,{attr=$name});
push@{$object-{attributes}},$name;
}
delete$object-{attrs};
if(@{$object-{attributes}}){
$object-{attributes}=[sort@{$object-{attributes}}];
}else{
delete$object-{attributes};
}
$object-{time}=~tr/-/:-/;
$object-{obj_descr}=Message:get_phrase('O',$object,{});
$sd-{objects}{$object-{ref}}||=[];
push@{$sd-{objects}{$object-{ref}}},$object;
}
}
$db-disconnect;
return$sessions;
}代碼分析:
從數據庫reporting中分別執行以下操作實現數據讀取:
sessions:SELECTsid,facility,srcip,username,time,endtime,stateFROMconfd_sessions;
nodes:SELECT*FROMconfd_nodes;
objects:SELECT*FROMconfd_objects;經過測試分析,confd_sessions存儲Session信息。
讀取Session信息的cmd命令:
psqlreporting-Upostgres-c'SELECTsid,facility,srcip,username,time,endtime,stateFROMconfd_sessions;'(2)文件操作
關鍵代碼:
sub_iterate_files{
my($self,$args)=@_;
#choosethefirstfiletoprocess
my$filename='/var/log/confd.log';
if(defined$args-{time}){
my@then;
if($args-{time}=~/^(\d{4}):(\d\d):(\d\d)/){
@then=(0,0,12,$3,$2-1,$1-1900);
}else{
@then=localtime($args-{time});
}
my$then=POSIX:strftime('%F',@then);
my$now=POSIX:strftime('%F',localtime);
$filename=POSIX:strftime(
'/var/log/confd/%Y/%m/confd-%Y-%m-%d.log.gz',
@then,
)if$thenne$now;
}
#processthefirstfile
my$sessions=[];
my$sdata={};
_parse_file($self,$filename,$sessions,$sdata,$args);
#ifneeded,processarchivedlogfiles
if(@$sessions$args-{max}not$args-{time}){
my$iter=File:Next:files({
file_filter=sub{/\.log\.gz$/},
sort_files=\File:Next:sort_reverse,
},'/var/log/confd');
while(@$sessions$args-{max}){
$filename=$iter-();
lastunlessdefined$filename;
my@new_sessions;
_parse_file($self,$filename,\@new_sessions,$sdata,$args);
push@$sessions,@new_sessions;
}
}
#limitthenumberofsessionstoreporton
splice@$sessions,$args-{max}if@$sessions=$args-{max};
return[@{$sdata}{@$sessions}];
}代碼分析:
讀取文件/var/log/confd.log,/var/log/confd.log只能保存現在時間到之前一段時間的日誌,更早時間的日誌會保存在/var/log/confd/%Y/%m/confd-%Y-%m-%d.log.gz,例如2022年5月16日的日誌對應位置為/var/log/confd/2022/05/confd-2022-05-16.log.gz
經過測試分析,/var/log/confd.log存儲Session信息。
7.編輯文件中存儲的Session信息查看登錄成功的信息:
cat/var/log/confd.log|grepsuccess返回結果示例:
2022:05:23-00:19:33testconfd[41177]:IRole:authenticate:185()=id='3106'severity='info'sys='System'sub='confd'name='authenticat ionsuccessful'user='admin'srcip='192.168.1.2'sid='8ad7bbf2781b006d99176eea9050694811e745e04acfab3dd0179620109a41ab'facility='webadmin'client='webadmin.plx'cal l='new'May2300:19:33confd[41177]:Dsys:AUTOLOAD:307()=id='3100'severity='debug'sys='System'sub='confd'name='externalcall'user='admin's rcip='192.168.1.2'facility='webadmin'client='webadmin.plx'lock='none'method='get_SID'從結果中獲得sid為8ad7bbf2781b006d99176eea9050694811e745e04acfab3dd0179620109a41ab
篩選出指定sid的信息:
cat/var/log/confd.log|grep8ad7bbf2781b006d99176eea9050694811e745e04acfab3dd0179620109a41ab返回結果示例:
2022:05:23-00:19:33testconfd[41177]:IRole:authenticate:185()=id='3106'severity='info'sys='Sys
Recommended Comments