Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
6619f2ed
Commit
6619f2ed
authored
Aug 14, 2012
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented -x option
parent
33853cd5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
41 additions
and
23 deletions
+41
-23
mongoose.1
mongoose.1
+3
-0
mongoose.c
mongoose.c
+18
-13
test.pl
test/test.pl
+20
-10
No files found.
mongoose.1
View file @
6619f2ed
...
...
@@ -143,6 +143,9 @@ will serve all URLs that start with "/config" from the "/etc" directory, and
call handle_doc.cgi script for .doc and .rtf file requests. If some pattern
matches, no further matching/substitution is performed
(first matching pattern wins). Use full paths in substitutions. Default: ""
.It Fl x Ar hide_files_patterns
A prefix pattern for the files to hide. Files that match the pattern will not
show up in directory listing and return 404 Not Found if requested. Default: ""
.El
.Pp
.Sh EMBEDDING
...
...
mongoose.c
View file @
6619f2ed
...
...
@@ -408,14 +408,15 @@ struct socket {
int
is_ssl
;
// Is socket SSL-ed
};
// NOTE(lsm): this enum shoulds be in sync with the config_options below.
enum
{
CGI_EXTENSIONS
,
CGI_ENVIRONMENT
,
PUT_DELETE_PASSWORDS_FILE
,
CGI_INTERPRETER
,
PROTECT_URI
,
AUTHENTICATION_DOMAIN
,
SSI_EXTENSIONS
,
ACCESS_LOG_FILE
,
SSL_CHAIN_FILE
,
ENABLE_DIRECTORY_LISTING
,
ERROR_LOG_FILE
,
GLOBAL_PASSWORDS_FILE
,
INDEX_FILES
,
ENABLE_KEEP_ALIVE
,
ACCESS_CONTROL_LIST
,
MAX_REQUEST_SIZE
,
EXTRA_MIME_TYPES
,
LISTENING_PORTS
,
DOCUMENT_ROOT
,
SSL_CERTIFICATE
,
NUM_THREADS
,
RUN_AS_USER
,
REWRITE
,
EXTRA_MIME_TYPES
,
LISTENING_PORTS
,
DOCUMENT_ROOT
,
SSL_CERTIFICATE
,
NUM_THREADS
,
RUN_AS_USER
,
REWRITE
,
HIDE_FILES
,
NUM_OPTIONS
};
...
...
@@ -443,6 +444,7 @@ static const char *config_options[] = {
"t"
,
"num_threads"
,
"10"
,
"u"
,
"run_as_user"
,
NULL
,
"w"
,
"url_rewrite_patterns"
,
NULL
,
"x"
,
"hide_files_patterns"
,
NULL
,
NULL
};
#define ENTRIES_PER_CONFIG_OPTION 3
...
...
@@ -858,7 +860,6 @@ static void send_http_error(struct mg_connection *conn, int status,
// Errors 1xx, 204 and 304 MUST NOT send a body
if
(
status
>
199
&&
status
!=
204
&&
status
!=
304
)
{
len
=
mg_snprintf
(
conn
,
buf
,
sizeof
(
buf
),
"Error %d: %s"
,
status
,
reason
);
cry
(
conn
,
"%s"
,
buf
);
buf
[
len
++
]
=
'\n'
;
va_start
(
ap
,
fmt
);
...
...
@@ -2385,6 +2386,13 @@ static int WINCDECL compare_dir_entries(const void *p1, const void *p2) {
return
query_string
[
1
]
==
'd'
?
-
cmp_result
:
cmp_result
;
}
static
int
must_hide_file
(
struct
mg_connection
*
conn
,
const
char
*
path
)
{
const
char
*
pw_pattern
=
"**"
PASSWORDS_FILE_NAME
"$"
;
const
char
*
pattern
=
conn
->
ctx
->
config
[
HIDE_FILES
];
return
match_prefix
(
pw_pattern
,
strlen
(
pw_pattern
),
path
)
>
0
||
(
pattern
!=
NULL
&&
match_prefix
(
pattern
,
strlen
(
pattern
),
path
)
>
0
);
}
static
int
scan_directory
(
struct
mg_connection
*
conn
,
const
char
*
dir
,
void
*
data
,
void
(
*
cb
)(
struct
de
*
,
void
*
))
{
char
path
[
PATH_MAX
];
...
...
@@ -2398,11 +2406,12 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
de
.
conn
=
conn
;
while
((
dp
=
readdir
(
dirp
))
!=
NULL
)
{
// Do not show current dir and
passwords file
// Do not show current dir and
hidden files
if
(
!
strcmp
(
dp
->
d_name
,
"."
)
||
!
strcmp
(
dp
->
d_name
,
".."
)
||
!
strcmp
(
dp
->
d_name
,
PASSWORDS_FILE_NAME
))
must_hide_file
(
conn
,
dp
->
d_name
))
{
continue
;
}
mg_snprintf
(
conn
,
path
,
sizeof
(
path
),
"%s%c%s"
,
dir
,
DIRSEP
,
dp
->
d_name
);
...
...
@@ -3399,9 +3408,6 @@ static void handle_request(struct mg_connection *conn) {
// Do nothing, callback has served the request
}
else
if
(
!
strcmp
(
ri
->
request_method
,
"OPTIONS"
))
{
send_options
(
conn
);
}
else
if
(
strstr
(
path
,
PASSWORDS_FILE_NAME
))
{
// Do not allow to view passwords files
send_http_error
(
conn
,
403
,
"Forbidden"
,
"Access Forbidden"
);
}
else
if
(
conn
->
ctx
->
config
[
DOCUMENT_ROOT
]
==
NULL
)
{
send_http_error
(
conn
,
404
,
"Not Found"
,
"Not Found"
);
}
else
if
((
!
strcmp
(
ri
->
request_method
,
"PUT"
)
||
...
...
@@ -3418,12 +3424,11 @@ static void handle_request(struct mg_connection *conn) {
send_http_error
(
conn
,
500
,
http_500_error
,
"remove(%s): %s"
,
path
,
strerror
(
ERRNO
));
}
}
else
if
(
stat_result
!=
0
)
{
}
else
if
(
stat_result
!=
0
||
must_hide_file
(
conn
,
path
)
)
{
send_http_error
(
conn
,
404
,
"Not Found"
,
"%s"
,
"File not found"
);
}
else
if
(
st
.
is_directory
&&
ri
->
uri
[
uri_len
-
1
]
!=
'/'
)
{
(
void
)
mg_printf
(
conn
,
"HTTP/1.1 301 Moved Permanently
\r\n
"
"Location: %s/
\r\n\r\n
"
,
ri
->
uri
);
(
void
)
mg_printf
(
conn
,
"HTTP/1.1 301 Moved Permanently
\r\n
"
"Location: %s/
\r\n\r\n
"
,
ri
->
uri
);
}
else
if
(
!
strcmp
(
ri
->
request_method
,
"PROPFIND"
))
{
handle_propfind
(
conn
,
path
,
&
st
);
}
else
if
(
st
.
is_directory
&&
...
...
@@ -4322,7 +4327,7 @@ struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
return
NULL
;
}
if
(
ctx
->
config
[
i
]
!=
NULL
)
{
cry
(
fc
(
ctx
),
"%s: duplicate option"
,
name
);
cry
(
fc
(
ctx
),
"
warning:
%s: duplicate option"
,
name
);
}
ctx
->
config
[
i
]
=
mg_strdup
(
value
);
DEBUG_TRACE
((
"[%s] -> [%s]"
,
name
,
value
));
...
...
test/test.pl
View file @
6619f2ed
...
...
@@ -174,14 +174,20 @@ my $cmd = "$exe ".
'-put_delete_passwords_file test/passfile '
.
'-access_control_list -0.0.0.0/0,+127.0.0.1 '
.
"-document_root $root "
.
"-hide_files_patterns **exploit.pl "
.
"-enable_keep_alive yes "
.
"-url_rewrite_patterns /aiased=/etc/,/ta=$test_dir"
;
$cmd
.=
' -cgi_interpreter perl'
if
on_windows
();
spawn
(
$cmd
);
my
$x
=
'x='
.
'A'
x
(
200
*
1024
);
my
$len
=
length
(
$x
);
o
(
"POST /env.cgi HTTP/1.0\r\nContent-Length: $len\r\n\r\n$x"
,
'^HTTP/1.1 200 OK'
,
'Long POST'
);
o
(
"GET /hello.txt HTTP/1.1\n\n GET /hello.txt HTTP/1.0\n\n"
,
'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close'
,
'Request pipelining'
,
2
);
my
$x
=
'x='
.
'A'
x
(
200
*
1024
);
my
$len
=
length
(
$x
);
o
(
"POST /env.cgi HTTP/1.0\r\nContent-Length: $len\r\n\r\n$x"
,
'^HTTP/1.1 200 OK'
,
'Long POST'
);
# Try to overflow: Send very long request
req
(
'POST '
.
'/..'
x
100
.
'ABCD'
x
3000
.
"\n\n"
,
0
);
# don't log this one
...
...
@@ -245,7 +251,8 @@ o("GET /$test_dir_uri/x/ HTTP/1.0\n\n",
"SCRIPT_FILENAME=test/test_dir/x/index.cgi"
,
'SCRIPT_FILENAME'
);
o
(
"GET /ta/x/ HTTP/1.0\n\n"
,
"SCRIPT_NAME=/ta/x/index.cgi"
,
'Aliases SCRIPT_NAME'
);
o
(
"GET /hello.txt HTTP/1.1\n\n"
,
'Connection: close'
,
'No keep-alive'
);
o
(
"GET /hello.txt HTTP/1.1\nConnection: close\n\n"
,
'Connection: close'
,
'No keep-alive'
);
$path
=
$test_dir
.
$dir_separator
.
'x'
.
$dir_separator
.
'a.cgi'
;
system
(
"ln -s `which perl` $root/myperl"
)
==
0
or
fail
(
"Can't symlink perl"
);
...
...
@@ -253,11 +260,6 @@ write_file($path, "#!../../myperl\n" .
"print \"Content-Type: text/plain\\n\\nhi\";"
);
chmod
(
0755
,
$path
);
o
(
"GET /$test_dir_uri/x/a.cgi HTTP/1.0\n\n"
,
"hi"
,
'Relative CGI interp path'
);
#o("GET /hello.txt HTTP/1.1\n\n GET /hello.txt HTTP/1.0\n\n",
# 'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close',
# 'Request pipelining', 2);
o
(
"GET * HTTP/1.0\n\n"
,
"^HTTP/1.1 404"
,
'* URI'
);
my
$mime_types
=
{
...
...
@@ -343,6 +345,14 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
"realm=\"mydomain.com\", nonce=\"1291376417\", uri=\"/\","
.
"response=\"e8dec0c2a1a0c8a7e9a97b4b5ea6a6e6\", qop=auth, nc=00000001, cnonce=\"1a49b53a47a66e82\""
;
o
(
"GET /hello.txt HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'HTTP/1.1 200 OK'
,
'GET regular file with auth'
);
o
(
"GET / HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'^(.(?!(.htpasswd)))*$'
,
'.htpasswd is hidden from the directory list'
);
o
(
"GET / HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'^(.(?!(exploit.pl)))*$'
,
'hidden file is hidden from the directory list'
);
o
(
"GET /.htpasswd HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'^HTTP/1.1 404 '
,
'.htpasswd must not be shown'
);
o
(
"GET /exploit.pl HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'^HTTP/1.1 404'
,
'hidden files must not be shown'
);
unlink
"$root/.htpasswd"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment