2010-04-22, 19:25
  #13
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av metapod
IRC-protokollet separerar de olika commands som skickas från servern med en radbrytbning. Således borde denna radbrytning, som du säger, försvinna vid eventuell split om du gör på rätt sätt.

Det du dock måste ha i åtanke är att vissa IRC-servers skickar ut endast "\n" istället för "\r\n" - vilket kan ligga bakom det du beskrivit tidigare..

Finns det någon funktion eller något som skriver ut alla kontrolltecken som en sträng istället för det dom egentligen ska göra?

EDIT: Har lokaliserat problemet, när jag splittar indatat så blir varannan rad tom, jag skrev ut radnumret innan varje rad och då såg det ut såhär:

0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
__________________
Senast redigerad av AquaRegia 2010-04-22 kl. 19:31.
Citera
2010-04-22, 19:37
  #14
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Finns det någon funktion eller något som skriver ut alla kontrolltecken som en sträng istället för det dom egentligen ska göra?
Du kan göra det med pprint:
Kod:
import pprint

pprint
.pprint("1\t2\r\n3"
pprint är även bra på att skriva ut annat, såsom stora listor och dictar.

Citat:
EDIT: Har lokaliserat problemet, när jag splittar indatat så blir varannan rad tom, jag skrev ut radnumret innan varje rad och då såg det ut såhär:

0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
Jag vill även tipsa dig om twisted om du inte redan känner till det. I följande tråd ger jag ett exempel på hur det kan användas för en IRC-bot:
https://www.flashback.org/t1031095
Citera
2010-04-22, 19:43
  #15
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av SSH
Du kan göra det med pprint:
Kod:
import pprint

pprint
.pprint("1\t2\r\n3"
pprint är även bra på att skriva ut annat, såsom stora listor och dictar.


Jag vill även tipsa dig om twisted om du inte redan känner till det. I följande tråd ger jag ett exempel på hur det kan användas för en IRC-bot:
https://www.flashback.org/t1031095

Twisted lät rätt nice, men just nu skriver jag från scratch för att lära mig lite om sockets och sånt.

Jag tror att problemet ligger i att om man splittar t.ex. "abcdef" med "f", så får man en lista med två strängar, "abcde" och "".
Citera
2010-04-22, 19:46
  #16
Medlem
metapods avatar
Citat:
Ursprungligen postat av AquaRegia
EDIT: Har lokaliserat problemet, när jag splittar indatat så blir varannan rad tom, jag skrev ut radnumret innan varje rad och då såg det ut såhär:

0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
0: <AquaRegia> test
1:
Citat:
Ursprungligen postat av AquaRegia
Jag tror att problemet ligger i att om man splittar t.ex. "abcdef" med "f", så får man en lista med två strängar, "abcde" och "".

Vilket är en naturlig följd utav att du delar en sträng som ej innehåller något efter din delimiter, vilket gör att andra delen utav din returnerade array blir tom. Du får helt enkelt sortera ut dessa tomma element på ett eller annat sätt, finns många tillvägagångssätt (bl.a med funktionen filter);

Kod:
print filter (
  lambda elem: elem,
  "data::atad:".split (':')
)
Kod:
['data', 'atad']
Citera
2010-04-22, 19:51
  #17
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av metapod
Vilket är en naturlig följd utav att du delar en sträng som ej innehåller något efter din delimiter, vilket gör att andra delen utav din returnerade array blir tom. Du får helt enkelt sortera ut dessa tomma element på ett eller annat sätt, finns många tillvägagångssätt (bl.a med funktionen filter);

Kod:
print filter (
  lambda elem: elem,
  "data::atad:".split (':')
)
Kod:
['data', 'atad']

Om jag har tänkt rätt så är det bara det sista elementet som blir en tom sträng, så om indatat är:

text1\r\n
text2\r\n
text3\r\n

så blir listan:

["text1","text2","text3",""]

Så jag löste det genom att helt enkelt ta bort det sista elementet, får se hur länge den lösningen håller...

lista = lista[:-1]
Citera
2010-04-22, 20:04
  #18
Medlem
metapods avatar
Citat:
Ursprungligen postat av AquaRegia
Så jag löste det genom att helt enkelt ta bort det sista elementet, får se hur länge den lösningen håller...]

OVanstående lösning kommer att hålla i ditt fall. Ville bara passa på att visa hur man filtrerar bort oönskade element (i det här fallet tomma strängar) ur en lista. Kändes relevant då en vanlig följdfråga angående hur man bör få bort vissa element (oavsett plats) är just detta.
Citera
2010-04-26, 20:11
  #19
Medlem
AquaRegias avatar
Om jag nu vill att andra ska kunna använda botten lite smått, vad ska jag tänka på att filtrera?

Bara acceptera kommandon som inte innehåller ; eller .

Räcker det? Eller behövs det mer? Kan man göra något farligt med en rad kod utan ; och .?
Citera
2010-04-26, 20:57
  #20
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Om jag nu vill att andra ska kunna använda botten lite smått, vad ska jag tänka på att filtrera?

Bara acceptera kommandon som inte innehåller ; eller .

Räcker det? Eller behövs det mer? Kan man göra något farligt med en rad kod utan ; och .?
Det räcker absolut inte. Man bör ha i åtanke att användaren genom exec inte bara kan anropa funktioner och dylikt, utan även importera saker, saker som sedan kan anropas:
Kod:
exec "from os import system"
exec "system('rm -rf /')" 
Man kan ju förbjuda all användning av import, fast funktionaliteten blir då starkt begränsad. Det skulle inte heller förvåna mig att det går att ställa till med oreda, även utan någon import. Det är även knepigt rent generellt att filtrera, finns hur många fällor som helst, bland annat att användaren inte skickar import direkt utan gör något trick med teckenkodningen. Man bör också ha i åtanke att det inte enbart finns ett import-statement utan att det även finns en __import__-funktion som returnerar det som importerats.

Vill du begränsa vad användaren kan göra så har eval större stöd för detta än exec. Används eval så kan inte statements som print användas, men man kan ju alltid definiera sin egen print-funktion som använder ett print-statement om man har det behovet. När man anropar eval kan man skicka med en eller två dictar med moduler som användaren tillåts använda:
http://docs.python.org/library/functions.html#eval
Skulle dock inte förlita mig helt på eval själv, utan skulle istället skrivit något eget. Kanske är jag onödigt paranoid.
Citera
2010-04-26, 21:53
  #21
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av SSH
Det räcker absolut inte. Man bör ha i åtanke att användaren genom exec inte bara kan anropa funktioner och dylikt, utan även importera saker, saker som sedan kan anropas:
Kod:
exec "from os import system"
exec "system('rm -rf /')" 
Man kan ju förbjuda all användning av import, fast funktionaliteten blir då starkt begränsad. Det skulle inte heller förvåna mig att det går att ställa till med oreda, även utan någon import. Det är även knepigt rent generellt att filtrera, finns hur många fällor som helst, bland annat att användaren inte skickar import direkt utan gör något trick med teckenkodningen. Man bör också ha i åtanke att det inte enbart finns ett import-statement utan att det även finns en __import__-funktion som returnerar det som importerats.

Vill du begränsa vad användaren kan göra så har eval större stöd för detta än exec. Används eval så kan inte statements som print användas, men man kan ju alltid definiera sin egen print-funktion som använder ett print-statement om man har det behovet. När man anropar eval kan man skicka med en eller två dictar med moduler som användaren tillåts använda:
http://docs.python.org/library/functions.html#eval
Skulle dock inte förlita mig helt på eval själv, utan skulle istället skrivit något eget. Kanske är jag onödigt paranoid.

Men kan man importera någonting och använda det på en rad utan ;?

import urllib; urllib.open(blablabla)...

Så brukar det se ut, och kör man först en import på en rad, och försöker göra något med det importerade på nästa rad så fungerar inte det. Var ligger __import__? Kan man komma åt den utan punktnotation?
Citera
2010-04-26, 22:38
  #22
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Men kan man importera någonting och använda det på en rad utan ;?

import urllib; urllib.open(blablabla)...

Så brukar det se ut, och kör man först en import på en rad, och försöker göra något med det importerade på nästa rad så fungerar inte det.
Använder programmet exec rakt av behöver det som körs inte vara på samma rad eftersom programmet kommer ihåg sånt som körts tidigare. En illasinnad användare kan alltså skicka två kommandon. Standardsättet att göra det på en rad är annars:
Kod:
__import__('os').system("rm -rf /"
Citat:
Var ligger __import__? Kan man komma åt den utan punktnotation?
Eftersom __import__ är en inbyggd funktion ligger den i modulen __builtins__. Själva __import__ kan användas utan punktnotation, men det som returneras anropas vanligen med punktnotation.

Tillåts användaren att exekvera flera kommandon hjälper det inte heller att bara leta efter . och import eftersom användaren kan skicka data kodat och sedan konstruera sina egna strängar som sedan körs med eval:
Kod:
punkt chr(46)
'i'
str "__%smport__('os')%ssystem('rm -rf')" % (ipunkt)
eval(
str
Man måste alltså också leta efter eval och exec. Det finns också många andra otäcka funktioner och statements, bland annat del-statemetet.

Jag tror, men är inte säker på att man kan hindra exec från att komma ihåg sånt från tidigare kommando om man skapar en ny process som tar hand om varje nytt kommando.

Vad vill du egentligen åstadkomma? Funktionaliteten för användaren blir rätt så meningslös om programmet inte har något minne från tidigare kommandon och om den mest funktionaliteten förbjuds. Det blir ju nästan enklare om du implementerar den begränsade funktionaliteten själv istället för att använda eval/exec och sedan försöka undvika alla möjliga säkerhetsrisker.
Citera
2010-04-26, 22:51
  #23
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av SSH
Använder programmet exec rakt av behöver det som körs inte vara på samma rad eftersom programmet kommer ihåg sånt som körts tidigare. En illasinnad användare kan alltså skicka två kommandon. Standardsättet att göra det på en rad är annars:
Kod:
__import__('os').system("rm -rf /"

Eftersom __import__ är en inbyggd funktion ligger den i modulen __builtins__. Själva __import__ kan användas utan punktnotation, men det som returneras anropas vanligen med punktnotation.

Tillåts användaren att exekvera flera kommandon hjälper det inte heller att bara leta efter . och import eftersom användaren kan skicka data kodat och sedan konstruera sina egna strängar som sedan körs med eval:
Kod:
punkt chr(46)
'i'
str "__%smport__('os')%ssystem('rm -rf')" % (ipunkt)
eval(
str
Man måste alltså också leta efter eval och exec. Det finns också många andra otäcka funktioner och statements, bland annat del-statemetet.

Jag tror, men är inte säker på att man kan hindra exec från att komma ihåg sånt från tidigare kommando om man skapar en ny process som tar hand om varje nytt kommando.

Vad vill du egentligen åstadkomma? Funktionaliteten för användaren blir rätt så meningslös om programmet inte har något minne från tidigare kommandon och om den mest funktionaliteten förbjuds. Det blir ju nästan enklare om du implementerar den begränsade funktionaliteten själv istället för att använda eval/exec och sedan försöka undvika alla möjliga säkerhetsrisker.

Som det är nu så kommer den inte ihåg vad som hänt tidigare, dvs:

Kod:
[22:46] <AquaRegia> import urllib
[22:46] <PyBot> No output!
[22:46] <AquaRegia> print urllib.urlopen("www.google.com").read()[0]
[22:46] <PyBot> Error: name 'urllib' is not defined

Men det gör inte så mycket, man kan trots allt göra rätt kraftfulla saker på en rad.

Egentligen så vill jag att alla ska kunna göra allt som inte på något sätt är "skadligt", men jag vet att det är helt orimligt, så jag försöker hitta någonting som är nära nog.
Citera
2010-04-26, 23:42
  #24
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Som det är nu så kommer den inte ihåg vad som hänt tidigare, dvs:

Kod:
[22:46] <AquaRegia> import urllib
[22:46] <PyBot> No output!
[22:46] <AquaRegia> print urllib.urlopen("www.google.com").read()[0]
[22:46] <PyBot> Error: name 'urllib' is not defined
Hur implementerade du detta? exec och en ny process för varje kommando?
Citat:
Men det gör inte så mycket, man kan trots allt göra rätt kraftfulla saker på en rad.

Egentligen så vill jag att alla ska kunna göra allt som inte på något sätt är "skadligt", men jag vet att det är helt orimligt, så jag försöker hitta någonting som är nära nog.
Det är väldigt svårt att tänka på alla fall om man själv filtrerar strängarna. Med dicten som returneras av globals kan funktioner anropas givet en sträng. Med getattr kan funktioner anropas utan punktnotation. Exempel:
Kod:
getattr(getattr((globals()['__builtins__']), '__import__')('os'), 'system')('rm -rf /'
Strängliteralerna kan också bytas. '__import__' kan exempelvis ersättas med:
Kod:
getattr("""join")([chr(c) for c in [95951051091121111141169595]]) 
Finns säkert också många andra funktioner än eval, getattr och globals/locals du måste tänka på. Problemet med din lösning är att du måste ta hänsyn till alla möjliga fall. Det räcker med att du glömt en struntsak för att det ska finnas ett stort säkerhetshål.

Edit:
En idé är annars att helt enkelt ta bort __builtins__-modulen. Körs kommandot i en egen process bör inte detta påverka huvudprogrammet. Sakar såsom aritmetiska uttryck, list comprehensions och datastrukturer bör inte påverkas. Är dock inte säker på att alla potentiella säkerhetshål försvinner.
Kod:
del __builtins__ 
__________________
Senast redigerad av SSH 2010-04-26 kl. 23:48.
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in