#Ryle - Server-Side Template Injections
1 messages Β· Page 1 of 1 (latest)
Keep #djs-help-v14 clear
Yea this is basically the JS version of SQL Injection
You're turning the user's input, into executed code
man i dont use SQL
yea i get this tho
I know, it's just what I know
For SQL it can be SUPER BAD
Because you can do like:
SELECT * FROM <user input>
and the user's input is:
Customer; DROP TABLE Customer;
So you end up with 2 statements:
SELECT * FROM Customer;
DROP TABLE Customer; // AHHHHHHHHH!
no idea what any of that is about
World of Databases
So yea, don't do JS stuff like that
If the user gives a string, only ever have it a string.
Don't run it as code, or HTML, etc
so would a fix be, to check if the string is a command or something?
then to just return if it was anything that wasnt a command?
I'm feeling like getting lectured by Yinoguns sensei xD
Uhhh... No. You have to sanitize your comment first.
Nearly 8yrs Dev experience π you might learn something on the side
I'm just a hobbyist though π
same here
So can you explain what the original intent was?
basically i was asking for an explanation for some code someone helped me with. then Airgeddon saw the vulnerability
i still dont see where the template injection could be in the code to be honest
Oh, he was confused of what the require("./handeler/"+handele+".js")(client) in his code he copied was, so I explained it to him, and he still doesn't know what the code does, so I asked him to get the handle's js source code, so I can read it and explain it for him, and it happens to be handel that executes command from the user's message.
it doesnt, though
ah I see, yea doesn't sound good.
Feel free to DM me that 2nd code so I can understand
you can still inject the code at any point though...
i dont see where. im not taking any user input
Yea neither do I
He's shared me:
...
module.exports = (client) => {
readdirSync("./Commands/").forEach(dir => {
...
And it's a handler of commands, not a command itself
heres an example of what my handler.js file is pulling.
module.exports = {
name: "add",
aliases: ["create"],
description: "Add a date to the credits command. FORMAT: `yyyy-mm-dd`.",
run: async (client, interaction, args) => {```
That's not the full code?
they are just not sending all of it, i sent them the entire block
for (let file of commands) {
``` i believe this runs once for every file in commands
hence the ...s
Here is where im running the commands themselves. this is my code:
client.on('messageCreate', async (message) => {
if (message.author.id !== '406880301449478144') return;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const cmd = args.shift().toLowerCase();
if (cmd.length === 0) return;
let command = '';
let aliasCheck = client.aliases.get(cmd);
aliasCheck ? command = client.commands.get(aliasCheck) : command = client.commands.get(cmd)
// If aliasCheck is true, the first statement will run. If it is false, the second will run.
if (!message.content.startsWith(prefix) || message.author.bot) return;
if (command) {
...
at the end of if (command) {...
I use: command.run(client, message, args)
which only runs if the "command" is one of these
add, creditsd, help, ping, website, or any of the aliases to those commands
as far as user inputs go for all of those commands, all i do is take the user input and save it to a json file
and i do that with just a simple messageCollector.
const dateCollector = interaction.channel.createMessageCollector({
filter,
time: 15000,
max: 1
});
``` so i think im safe?
i watched the video, no where in my code anywhere am i executing user input
Yea, long as you're not running eval or anything, even if they write console.log(env) in their input, it'll just be saved as "console.log(env)" (a string)
even if they write console.log(env) in their input, it'll just be saved as "console.log(env)" (a string)
can you explain this a bit more
I think it's safe becuase it's not using any eval and it checks the user id
well even if it didnt check the user id, no eval is anywhere in this bot
So like how in Discord, if I write console.log(env) it doesn't go to the server, run that code, and return.
It's just text.
No different than 123 while it "looks" like a number, being considered text
i dont know what console.log(env) is
oh wait
im stupid
yea i get what youre saying
You can somehow maneuver through it though, and you might be able to do sth like regex denial of service, but i think the regex is also safe.. I hope
i'll give you all of my index.js code if you wanna check 
client.on('messageCreate', async (message) => {
if (message.author.id !== '406880301449478144') return;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const cmd = args.shift().toLowerCase();
if (cmd.length === 0) return;
let command = '';
let aliasCheck = client.aliases.get(cmd);
aliasCheck ? command = client.commands.get(aliasCheck) : command = client.commands.get(cmd)
// If aliasCheck is true, the first statement will run. If it is false, the second will run.
if (!message.content.startsWith(prefix) || message.author.bot) return;
if (command) {
/*let today = new Date()
let currentHoursMilitary = today.getHours()
let suffix = currentHoursMilitary >= 12 ? "PM" : "AM";
let currentHours = ((currentHoursMilitary + 11) % 12 + 1)
let currentMinutes = today.getMinutes()
if (currentMinutes.toString().length === 1) {
let currentMinutesSingle = "0" + currentMinutes
// Hours are over 12, so it's been subtracted. Minute length is 1 character.
console.log(`[${currentHours}:${currentMinutesSingle} ${suffix}] ${message.author.tag} ran: ${prefix}${cmd}`)
} else {
// Hours are over 12, so it's been subtracted. Minute length is 2 characters.
console.log(`[${currentHours}:${currentMinutes} ${suffix}] ${message.author.tag} ran: ${prefix}${cmd}.`)
}*/
command.run(client, message, args)
}
});```
thats the only messageCreate event i have
and half of that is just a clock
or more specifically just logging the time
All that is fine β
Yeah, it's fine.
and if in a command im getting user input, but using a messagecollector, thats fine too?
I sorry for all the ruckus I caused. I misunderstood the code. I'm a bad coder.
nah bro, i didnt even know about all this vulnerability stuff before this 
ended up being good for me. i knew that a user having access to eval was bad but didnt know it could be done in many other ways
thanks for ur guys help and concern too
Awww thanks! β€οΈ
yea
well i almost sharted my pants, though. only downside
ive used this code with BIG bots before. had me rethinking how lucky ive been over the past year or so
well not huge, but like big enough to where there was probably one bad person in the bunch
Code is a complex beast, long as you're willing to learn and listen, you'll do fine.
yea been trying to learn. honestly i kind of took the stupid route and learned JS and discordjs at the same time. so when it comes to parameters and stuff like that sometimes i cant fully grasp it
if (array.some(word => testString.includes(word))) {
``` basic example, i dont get what `word` actually is. like i know its gonna end up being every value in the array i think
actually, this entire thing started because i didnt understand a function
This approach to programming is called functional programming. Very useful!
and clean
So workd => ... is called a "callback function"
It's just a "do this with everything"
"this" being checking to see if the string includes it?
yes
e.g:
[1, 2, 3, 4, 5].filter(val => val > 2)
That just gets each value greater than 2, where val is each value from the Array
so the filter will run 5 times, each time val will be something different
so in essence...
if (array.some(word => testString.includes(word))) {
}
for (let i = 0; i < array.length; i++) {
console.log(array[i])
if (testString.includes(array[i])) {
console.log(true)
}
}
``` are these two one and the same?
Sorta yea.
The "callback function" will run "per item"
5 items, 5 runs.
filter is just useful because you can use it instead of:
const myArray = [1, 2, 3, 4, 5];
let newArray = [];
for (let i = i; i < myArray.length; i++) {
if (myArray[i] > 2) {
newArray.push(myArray[i]);
}
}
so yes these are the same, but the callback function one is way cleaner
Indeed
also, once the callback function is over, will the initial array just end up being the numbers that pass the filter?
[3, 4, 5]
No, .filter returns a new array, so you have to:
const newArray = myArray.filter(...);
Some Array functions, do edit the original, JS is a funky bastard π
Callbacks are used in alot of things, not just arrays
oh god that was the answer i was not hoping for
It's just a concept of code, a function for a job
things just got more complicatd
Although, a bit slower, because V8 JIT doesn't compile it for performance, like on for loops (why, Google??), but that doesn't mean you shouldn't use it.
which ones slower
the functional prototype
so the .some()
also, i can see a downside of using the .some() being that it stops once its true
just use the .some() approach, it's way cleaner
I don't even use such $10 words π
You don't have to worry about function X over function Y for speed.
JS is still stupid fast, you'll lose fractions of MS if at all
is this right?
because the for loop will run as many times as it has to
but .some() stops
There are many functions:
.some
.find
.filter
.every
.map
.reduce
.forEach
Just depends on the job you need it to do
if (array.some(word => testString.includes(word))) { if i wanted this to NOT stop once it was true, and run for every single object in the array, what function would i need to use?
But why would you?
It's in an if so you're wanting to do something if any are true
So you might need to refactor; what's the purpose of the if?
thats true. but if it were something like a filter and i wanted to point out to the user every word they said that was flagged, i would want it to keep running
for (let i = 0; i < array.length; i++) {
console.log(array[i])
if (testString.includes(array[i])) {
console.log(true)
}
}
console.log('---------------------------------')
array.forEach(word => {
if (testString.includes(word)) {
console.log('Flagged')
}
})
``` and both of these seem to do the job. but theyre kind of big
ah, so you probably want .map followed with a .join
My suggestion here, is not to code it into your bot, but to use your chrome debugger
hit F12 in your browser
yea a console opens up
also im not coding this into my bot
this is a separate js file
['Hello', 'World', 'How', 'Are', 'You?']
.filter(word => word.includes('e'))
.map(word => `Flagged: ${word} (contained 'e')`)
// Result:
[
"Flagged: Hello (contained 'e')",
"Flagged: Are (contained 'e')"
]
OMG so clean! I wish I can code as clean as you xD
Have you used Reduce?
Never
what if the callback fn word in map was something else besides word, would the code still work? or is it remembering what word is from the filter fn?
['Hello', 'World', 'How', 'Are', 'You?']
.reduce((ac, word) => {
if (word.includes('e')) {
ac.push(`Flagged: ${word} (contained 'e')`);
}
return ac;
}, []);
All in 1
Yup, filter returns an Array, so Map receives that Array; Function Chaining
ive seen this kinda stuff before, what the heck is going on here if you dont mind explaining loll
- Me having an orgasm reading that * How did you come up with sth like this??
Reduce allows you to build something as you use it, so e.g. if you want to add a bunch of numbers together:
[1, 2, 3, 4, 5].reduce((total, val) => {
return total + val;
}, 0);
also decided to copy paste the code youre fanboying over lol ,
TypeError: Cannot read properties of undefined (reading 'You?')
``` confused
4yrs of University
Followed by nearly 8yrs of Development Experience
3-4yrs of SQL
3-4yrs of NodeJS and React
So the callback runs on each value:
Run 1:
total = 0,val = 1: 0 + 1 = 1
Run 2:total = 1,val = 2: 1 + 2 = 3
Run 3:total = 3,val = 3: 3 + 3 = 6
Run 4total = 6,val = 4: 6 + 4 = 10
Run 5:total = 10,val = 5: 10 + 5 = 15
Must have copied it wrong Β―_(γ)_/Β―
where is the 0 coming from
reduce takes 2 args, a callback function, and a starting value.
ah
But that value can be whatever you like: 0, {}, [], new Date(), etc
Must be an problem with the JS file, just use web browser debugger
One liner?
['Hello', 'World', 'How', 'Are', 'You?'].reduce((ac, word)=>{word.includes('e')?ac.push(Flagged: ${word} (contained 'e')):0;return ac;}, []);
lol
ugly af lol
Code isn't about being on "one line" it's about being Good, but Readable, and I personally value readability over magic.
If nobody else can take on your code because it's stupid mental magic, then it's bad code.
Yes, I'm aware. I just did it for laugh xD
I know π
It took me a while to understand reduce because the first time I saw it was a crazy one by my collegue, eventually something clicked, now I use them alot π
yea dont see myself using that a lot
ill stick to filter and map
cuz map just runs once for every object in an array right?
I'll have to improve myself. I have to learn how to conquer reduce. Very useful, thank you for educating us!
facts
i came to the chat to maybe learn a little from someone getting help or to help someone, and i just got lectured
(in a good way)
I spend a good bit of time helping a collegue who is new to coding, so I've learnt some good ways to explain things.
Never feel bad for not knowing something, and always feel good about learning.
yea
If you Google "MDN" + term You'll find JS docs, e.g:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
im honestly interested in getting a job in this industry, but im a junior in high school and im taking algebra 2 this year. feel like im kinda behind
yea, ive secretly been looking stuff up for later as we go lol. but taking advantage of this chance lol
ive taken 3 years of science, though, 2 of them being physics, so im still eligible for a 4 year. just probably not an insan eone
but ive heard that the industry of programming is HEAVILY competitive right now so you like NEED a comp sci degree to even get anywhere
and tbh, my coding skills dont go much further than basic js programs and discord bots. dont know where to start to make meaningful things
When I went to University, I did Computer Science, I learnt a lot ,but it no way fully prepared me for an actual Job, you learn SOOOO much more.
So focus on learning code, and learning practices.
I will take someone who knows good code, practices, and isn't a shithead, over a know-it-all who is actually bad at writing code or problem solving.
Why yes that is true, are you sure you dont need a degree to even get started?
My suggestion to you for now, is keep with Discord Bots.
You understand them, and can be enthuastic about them.
Just keep pushing the boundry, work on Slash Commands, then Buttons, then Menus, throw a Database in there, make a Currency System.
PUSH YOURSELF - and keep it fun, and just learn.
Make a Portfolio win!
Oof xD That hits me hard
I actually was doing really good... then my AWS ubuntu free period ended and i was getting charged $200-$300 a month to host my bot. big financial damage to a 17 year old 
Uni degree is more "I know how to do coding from a professional body" (but secretly I might still be shit)
getting a job in coding tho would be sick, it's something im passionate about and like doing
I know a platform you can use.
I host my 1 bot on it, 24hrs a day, every day a month, and it codes me Β£0/mo
- it has a DB
with no strings attached? no free trial that ends?
AWS bit me in the butt after 12 months
Nope, long as you're not making something for Commercial Earnings
I use AWS professionally at work, and I looked into it, but yea screw their costs
im assuming theres a threshold on your bitrate and storage usage though?
Linux YTbers "ThIs ViDeO iS sPoNsOrD bY LiNoDe"
The Server is a 512MB so yea that's a limitation
does it just limit you, or does it charge you if you go over
and the Database is I think 1GB or something, even if it's less it's more than I need
Limit, one of my early problems was the Bot crashing due to memory leak in my code, took me weeks to finally solve that bug π
because i have a bot that uses the presenceUpdate event, which can be heavy on bitrate i believe because presences change so often
basically, presence changes, it gives you a role depending on presence
(specifically streaming/listening to spotify)
oops wrong reply
Anyways, could you give me the name of the platform? I'd way rather my bot crash because of a limit than have the platform keep silent then just charge me out of nowhere
cuz that was a big thing that discouraged me...
Sent
There is one caveat
You get "free hours" but these hours are not enough for a whole month...unless, you register a payment card; then you get enough for 1 bot process to run round the clock.
It's not cost, it's just you register the card and you're gold
@frail vine
so if i dont register the card, i just have to deal with not being able to host my bot 24/7
and do these free hours replenish at the start of each month
yrs 
So enough for like 20d of uptime
haha, hrs*
But add the card, that's 40d and still free.
so do i gotta publish my bot to github to use heroku?
Imagine if they actually give you 500years of uptime xD
ah, atm GH pushing is broke due to a security issue, let me find the link
nah, i know github to an extent ill use that
oh shoot
Only question is, will the bot still be able to write data to a json file or am i gonna have to learn how to use MongoDB
Killing two birbs with 1 stone. Hosting + open sourcing
Not if Private Repo π₯·
wont people just steal my code 
Just use GPLv3
@frail vine This is link to explain how to register a Heroku Remote, and push to that; which deploys the bot.
https://help.heroku.com/CKVOUPSY/how-to-switch-deployment-method-from-github-to-heroku-git-with-all-the-changes-app-code-available-in-a-github-repo
not familiar with what a local repo is
Just the thing on your machine
so cmd prompt?
Wait local repo, huh
From the local repository's root directory, enter these commands:
ah do the folder of your project
so just go into my cmd prompt and go into my folder of the project then start doing this commands?
also ^^
There will be some effort in getting it setup
I think writing files might use up the Memory space, or even not be possible.
Are you using the files to track data?
yea
here
{
"683852656036413563": {
"userID": "406880301449478144",
"userTag": "Ryle#7974",
"roleID": "771122102254174279"
},
"651231560263008258": {
"userID": "406880301449478144",
"userTag": "Ryle#7974",
"roleID": "841742946776383508"
},
"720569527473012738": {
"roleID": "N/A"
},
"655316710751993868": {
"userID": "406880301449478144",
"userTag": "Ryle#0008",
"roleID": "960669367127912518"
}
}```
"server id": {
userID: userid
usertag: usertag
roleID: id of the role
}
Not sure why you need that, DJS knows all about users and members
guild.members.fetch('655316710751993868')
i just do it for when i look at it. makes it easier to see who changed the role
ah so it's an audit log?
kind of. but when the bot runs: newPresence.member.roles.add(listeningRole), listeningRole is pulled from that json file
from roleID
Either way, DB better.
It's the "right way" to do things, not the hacky JSON way π
yea ik json is bad. just the way i got familiar with
Don't want to go to an interview, discuss your bot, and them ask "why did you choose JSON for a storage medium"
plus not knowing DBs is bad enough... but on top of that id have to use DBs on heroku
yea not good
couldn't you just clone the object and then save it as a blob?
Heroku IIRC doesn't have DB, it's just a hosting service.
I have MongoDB through Atlas for a Free DB, the Bot connects to the DB that way
how does it connect to it? do you upload the DB to heroku too?
I have this:
databaseConnected = await new Promise((resolve) => {
try {
// noinspection JSVoidFunctionReturnValueUsed
mongoose.connect(MONGODB_SRV, {
useUnifiedTopology: true,
useNewUrlParser: true
// useFindAndModify: false, // option usefindandmodify is not supported
})
.then(() => {
resolve(true);
})
.catch(error => {
console.error('Database connection failed', error);
resolve(false);
});
} catch (error) {
console.error('Database connection failed', error);
resolve(false);
}
});
So mongoose.connect directly logs-in to the DB, from Heroku NodeJS instance
MongoDB is a separate host, through Atlas
I literally set it up, and haven't logged into it since.
I use Mongo Compass to view the data
hmm. gotta learn about that
oh that's a tip.
Make 2 Bots, and 2 Databases.
When you have it Live, it uses one bot and SRV for DB
When you run it on your machine, use the other pair.
And put each bot in it's own server; so they're all isolated.
Nothing worse than trying to do something and deleting Live data π±
Question: Why not use sth. like REDIS?
so youre basically saying that when the bot is running on heroku, just use a second bot as a "test bot"
Oh, no JS.... Damn
Exactly.
My Live Bot is always running
When I'm working on the bot, it's a different bot, with own server, and own git-branches
When I merge to main it deploys the changes to the live-bot
so you just upload the test bot files to github under the main bots repo
then host it?
I G2G, my work life needs attention π but if either of you have questions, you're both welcome to DB me
Ok. I probably should go to bed honestly
It's 1:30. I gotta do stuff in the morning but got really invested in this convo
we talked for like, almost 2 hours lol
thank you for your time
Ngl so confusing lol. Getting too late for me to dive into another topic tho. And your work life needs attention 
Anyways Iβll definitely be learning more as I go, Iβm taking a coding and game design class next year through the school I attend so hopefully theyβre any good. If not I just have 2 really easy classes.
Iβll probably try working on getting the bot up later tomorrow. Encouraging to know I can get back into bot developing for free